数据的表示与处理

一、基本知识

1. 字

  字是指计算机运算和传送数据的基本单位,其长度即为字长,字长指明了指针数据类型的大小。因此,字长表示了一个计算机的寻址范围,例如:32位机的指针占4个字节,其寻址范围就是0~2^32 - 1。

上面说的字长是机器字长,即CPU的字长,而操作系统字长不一定与机器字长一致(例如,在64位机器上装32位系统)。

2. C语言中基本数据类型的长度

  编译器对各种数据类型长度的定义是依据操作系统字长的,下表给出的是操作系统字长和机器字长一致时的情况:

C语言数据类型 32位机器 64位机器
char 1 1
short int 2 2
int 4 4
long int 4 8
long long int 8 8
指针类型 4 8
float 4 4
double 8 8

3. 数据对齐方式

  不同的机器在内存中存储字节的顺序可能不一样,主要分为小端模式与大端模式:

小端模式先存储数据的低字节,再存储高字节(低字节在低地址,高字节在高地址);

大端模式先存储数据的高字节,再存储低字节(高字节在低地址,低字节在高地址)。

  在两台采用不同对齐方式的计算机之间通过网络传递二进制数据时就会有一个问题:发送方发送的字节顺序与接收方接收的字节顺序是反序的。TCP/IP协议定义了统一的网络字节顺序(大端顺序),发送方在发送数据时将主机字节顺序转换成网络字节顺序后再发送出去,而接收方将网络字节顺序转换成主机字节顺序后再处理。Unix系统提供了以下函数来实现主机字节顺序和网络字节顺序的转换:

//主机字节顺序 to  网络字节顺序

  unsigned short int htons(unsigned short int);

  unsigned long int htonl(unsigned long int);

  // 网络字节顺序 to  主机字节顺序

unsigned short int ntohs(unsigned short int);

unsigned long int ntohl(unsigned long int);

  以上函数通常只在传递端口等数据时需要用到,而传递实际数据是不需要的,端口等数据是需要TCP/IP协议栈来解析的,必须转换成统一的字节序,而负载数据的顺序不是网络协议关心的事情。

4. 关于移位运算要注意的一点

  对一个数进行移位运算,当位移量K超过该数据类型的长度L时,实际通常会移动 K % L 位。但C语言标准没有规定这一点,而Java语言明确要求按照 K % L来计算实际的位移量。

5. 十进制数据快速转换成十六进制

  对于十进制数d,如果d = 2n,且n = k + 4m,(k < 4)。则d = 2 * (24)m,那么d可以写成为十六进制数:

0xp000...0 ,p = 2k,p后跟m个0

  例如:211 = 2048,211 = 23 * (24)2,则 2048 = 0x800。

那么,对于任意的十进制数d = 2n + q,n = k + 4m,(k < 4)。则我们可以先将2n 部分利用上述办法转换成十六进制数,然后再加上q即可。

  例如:2067 = 2048 + 19 = 0x800 + 19 = 0x813 。

二、整数表示

  1. 无符号整数的编码

  Uint =  Xw-12w-1 + Xw-22w-2 + ... + X020 ,无符号整数编码成w个二进制位,Xi表示第i位的值(0或者1),2i表示第i位的权值

  能表示的无符号整数的范围是 0 ~ 2w-1

  2. 有符号整数的编码

  Tint = -Xw-12w-1 + Xw-22w-2 + ... + X02,有符号整数编码成w个二进制位,与无符号整数的表示方式类似,只是第w-1位(最高位)的权值是-2w-1 

  能表示的有符号整数的范围是 -2w-1  ~  2w-1 - 1

3. 最大值与最小值

  Umin  = 0 ,Umax = 2w-1

Tmin  = -2w-1,Tmax = 2w-1 - 1

我们可以发现:

  |Tmin| = Tmax + 1 ,这是因为:一半的数表示负数(最高位为1),一半的数表示非负数(最高位为0),而非负数中包括0,于是能表示的整数就比负数少了一个。

  Umax = 2Tmax + 1 ,这是因为:在有符号整数表示中,所有的负数都成了整数,即Umax = |Tmin| + Tmax = 2Tmax  + 1 。

  4. 无符号整数和有符号整数的转换

  相同位数的无符号整数和有符号整数之间进行转换时,底层的位表示并没有发生变化,只是对这些位的解释发生了改变。

  用1和2中的 Uint - Tint 可得:Uint - Tint  = Xw-12w-1 - (-Xw-12w-1 ) = Xw-12w

那么有符号整数和无符号整数之间的转换函数如下:

  (1)有符号整数 -> 无符号整数

T2U = T + Xw-12,即:

当T > 0 时,Xw-1 = 0,T2U = T ,即等于原值;

   当T < 0 时,Xw-1 = 1,T2U = T + 2w ;

(2)无符号整数 -> 有符号整数

U2T = U - Xw-12w ,即:

    当U >= 2w-1 时,Xw-1 = 1,U2T = U - 2w ;

    当U < 2w-1 时,Xw-1 = 0,U2T = U;

  

  5. C语言中有符号整数和无符号整数的转换

  有符号整数和无符号整数的转换即按照4中的规则进行。C语言中,有符号整数和无符号整数可以通过强制转换进行,更值得注意的是有符号整数隐式转换为无符号整数。

  C语言中,若参与运算的两个整数一个是有符号整数,另一个是无符号整数,那么,有符号整数会被隐式地转换为无符号整数。

  上述规则可能会导致一些难以察觉的编程错误,我们需要注意。例如:

   float add(float num[],unsigned int length)

  {

int i = 0;

float sum = 0;

for(i = 0; i <= length - 1; i++)      // 减法是按加法来处理的

sum += num[i];

return sum;

     }

length声明为无符号整数类型,-1默认是有符号整数类型,那么-1会被转换成无符号整数,根据上面的转换规则U(-1) = 2w - 1,这样后面访问数组就会越界。

  当转换既涉及到大小转换也涉及符号转换时,C语言的转换规则是先进行大小转换,然后再进行符号转换,例如:unsigned int 转换为short int,先扩展位改变大小,再进行符号的转换。

  将较长字长的数字x转换为较短字长的数字时,会截去高k位,截断操作就相当于对x进行求余运算:x % 2

三、浮点数的表示

  1. 小数的二进制表示

    b = bmbm-1 ... b1b0 . b-1b-2 ... b-n ,其中小数点之前的权值分别为2m、2m-1 ... 21、20 ,小数点之后的权值为2-1、2-2 ... 2-n 

   小数的二进制表示法只能精确表示那些能够被写成x * 2y的数,其他数只能被近似表示。

  2. IEEE754浮点表示法

  IEEE754是浮点数表示的国际标准,采用 (-1)s  * M * 2来表示一个数,其中:

   s表示符号位,1表示负数,0表示正数;

     M表示尾数,是一个二进制小数;

     E表示阶码,对浮点数进行加权,E可以是负数;

看看32位浮点数表示法的位表示:

符号位S (占1位) 阶码E(占8位) 尾数M(占23位)

根据阶码E的位表示,可以分成以下几种情况:  

(1)规格化(E不全为0,也不全为1)

阶码E的位表示按照无符号整数来解释,其值e的范围即1 ~ 255,则E = e - (27-1),即E的取值范围是 -126 ~ 127 ;

 M隐含以1开头,尾数M的位表示只表示了小数部分,即最高位的权值为-1。

(2)非规格化(E全为0)

E = 1 - (27 - 1);

尾数M不再具有隐含的1,其值即为表示的小数部分的值。

规格化数中尾数M总是大于等于1,因此无法表示0,非规格化数主要用于表示0 :

  符号位S为0,阶码E全为0,尾数M全为0时,即表示+0.0;

  符号位S为1,阶码E全为0,尾数M全为0时,即表示-0.0;

非规格化数的E = 1 - (27 - 1),可以补偿尾数M不再包含的1。

(3)特殊值(E全为1)

当尾数M全为0时表示无穷大,符号位s为1表示负无穷大,s为0时表示正无穷大;

当尾数M非0时表示NaN(Not a Number)。

3. 浮点数的舍入

浮点数有一定的表示范围和精度,对于某些小数,只能近似表示它们,即必须对这些小数进行舍入后表示。默认采用向偶数舍入(round-to-even)的方式,以十进制小数为例,小数点后保留1位数:

当实际值不是正中间的值时,则向最接近的值舍入,例如:1.43舍入成1.4,1.47舍入成1.5;

  当实际值恰好是正中间的值时,则使得最低有效数字是偶数,例如:1.45舍入成1.4,而不是1.5。

时间: 2024-10-11 18:14:48

数据的表示与处理的相关文章

记一次MySQL找回用户数据

事情经过 有天,我们公司外区的一个销售C说他8月3号以前的工作流记录找不到了.问清缘由,原来是更新了微信号(我们公司的工作流是基于企业微信开发的).经过分析,微信号和流程数据并没什么关系,所以初步得出结论:本来只需要更新微信号的,结果我们公司的流程系统管理员把用户先删除,再创建了新的用户. 解决过程 1.首先想到的是直接从定时备份数据里面找回原来的用户ID,结果发现系统只备份了十天的记录,而工作流系统上显示销售C只有8月3号以后的流程记录,距今已经40多天,从自动备份的数据里已经无法恢复. 2.

使用 Chrome 浏览器插件 Web Scraper 10分钟轻松实现网页数据的爬取

本文标签: WebScraper Chrome浏览器插件 网页数据的爬取 使用Chrome 浏览器插件 Web Scraper 可以轻松实现网页数据的爬取,不写代码,鼠标操作,点哪爬哪,还不用考虑爬虫中的登陆.验证码.异步加载等复杂问题. Web Scraper插件 Web Scraper 官网中的简介: Web Scraper Extension (Free!)Using our extension you can create a plan (sitemap) how a web site

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

Oracle 10g通过创建物化视图实现不同数据库间表级别的数据同步

摘自:http://blog.csdn.net/javaee_sunny/article/details/53439980 目录(?)[-] Oracle 10g 物化视图语法如下 实例演示 主要步骤 在A节点创建原表和物化视图日志 在B节点创建连接A节点的远程链接 在B节点处创建目标表和与目标表名称相同的物化视图 在B节点处刷新物化视图 升级采用存储过程定时任务JOB方式定时刷新物化视图 进一步优化 文章更新记录 参考文章 Oracle 10g 物化视图语法如下: create materia

MySQL(九)之数据表的查询详解(SELECT语法)二

上一篇讲了比较简单的单表查询以及MySQL的组函数,这一篇给大家分享一点比较难得知识了,关于多表查询,子查询,左连接,外连接等等.希望大家能都得到帮助! 在开始之前因为要多表查询,所以搭建好环境: 1)创建数据表suppliers 前面已经有一张表是book表,我们在建立一张suppliers(供应商)表和前面的book表对应. 也就是说 让book中s_id字段值指向suppliers的主键值,创建一个外键约束关系. 其实这里并没有达到真正的外键约束关系,只是模拟,让fruits中的s_id中

C#如何拿到从http上返回JSON数据?

在实际开发中,我们经常会使用到API,所谓API一般就是一个地址,我们称之为接口.然后我们通过用C#对这地址发送请求,请求后,服务器就会给我们返回数据,一般是XML或者JSON,这里我们主要讲述的是JSON. 为了演示,我们这里准备了一个接口,这是一个查询物流的接口.(读者读到这篇文章的时候,接口可能有效,也可能失效,因为接口是网上找的,不是笔者自己写的,但是原理是一样的.) 接口:  http://www.kuaidi100.com/query?type=快递公司编码&postid=物流单号

C#中导出数据到Excel表格中

之前PM交给我一个自动化测试的Case,让我抓取页面上的数据到Excel表格中,刚好又接了一个之前人家做的系统, 刚好看到可以用NPOI导数据,就动手试试,成功导出. 由于鄙人比较菜,也比较懒, 怕自己忘记了,今天就总结一下,以防下次用可以参考. 1.要使用NPOI,首先需要在Project中Install NPOI的 Package. 右键点击Project------>Manage NuGet Packages---->Search NPOI----->点击搜索到的NPOI然后点击等

Oracle in 查询数据

问题描述: 查询所有的数据,查询结果:146360 select count(1) from bank_cde; in查询的获取部分数据,查询结果 :73080 select count(1) from bank_cde t where t.belongcode2 in('ABC','BCOM','BOC','CCB','CEB','CGB','CIB','CITIC','CMBC','ICBC','PAB','POST','SPDB'); not in查询数据,结果为0 select coun

SQL基础:数据表的创建

1. 先选择创建表所在的数据库 2. 创建表 3. 查看表是否创建成功 4. 主键:要求主键列的数据唯一,且不允许为空.主键能够唯一的标识表中的每一条记录,可以结合外键来定义不同数据表之间的关系,并且可以加快数据库查询的速度. 主键分为:单字段主键和多字段联合主键. 4.1 单字段主键 4.1.1 定义方式一:在定义列的同时指定主键 4.1.2 定义方式二:在定义完所有的列之后指定主键 4.2 多字段联合主键 5. 使用外键约束 外键用来在两个表之间建立连接,可以是一列或多列.一个表的外键可以是

MySQL binlog日志恢复数据

我们了解了MySQL 的 binlog 日志的开启方式以及 binlog 日志的一些原理和常用操作,我们知道,binlog 有两大作用,一个是使用 binlog 恢复数据,另一个就是用来做主从复制.本篇笔记就是来记录如何使用 binlog 日志来做数据恢复.当然了,使用 binlog 日志所恢复的数据只能是部分数据,并不能够使用 binlog 日志来做数据库的备份,如果想要做数据库备份,依然要使用我们传统的备份方法,而 binlog 可以作为增量备份. 视频链接:http://www.ronco