浮点数在计算机中存储方式

1.大端字节序和小端字节序

首先,咱们先得知道,在计算机内存中存储数据的格式有两种,一种是大端字节序(即将高位数据存放在低地址上,低位数据存放在高地址上),还有一种是小端字节序(与之前相反),举个例子:

一个short int短整型 3332 == 00001101 00000100,那么大部分机器中的存储方式为小端字节序
那就是这么存的: 00000100 00001101,也就是低位数据(4)放在低地址,高位数据(3328)放在高地址上。

x86,MOS Technology 6502,Z80,VAX,PDP-11等处理器为小端字节序,也就是说我们常用的绝大多数机器都是小端字节序。
知道了这一点再来讨论浮点数是如何存储在内存上的这个问题。

2.浮点数的计算方式,科学表示法

c/c++的所有编译器都是采用IEEE指定的标准浮点格式规则,即二进制科学表示法。

在这种表示方法中,一个数S = M*2^N
其中N表示阶码,M表示尾数(有效数字位),这里我们假定一个float型数,4个字节,32bit位
【31】 N:【30~23】 M:【22~0】

31位是符号位:0正,1负

中间8位是阶码位:表示范围为【-128~127】,对于float型数据规定其偏移量为127(下面解释)

后面23为是有效数字位:因为科学计数法,整数位定死了是1,所以这里记录的是小数点后面的二进制位

指数N决定它的范围,因为M总是一个以1开头的小数,以float来说即是:-2 ^ 128 ~~ 2 ^ 128,即float能表示的数的大小范围。

而它的精度是由尾数(也就是有效数据位)来决定的,2 ^ 23 == 8388608 ,总共7位,这表示最多能有7位有效数字,最多能表示到 .8388608 即小数点后7位,由于不能完全表示完全部的7位数,所以它的精度范围为6位~~7位。

同理可得double的精度是2 ^ 52 == 4503599627370496,共16位,所以精度为15~~16位。

3.具体该是怎么转换存到内存中去的呢?

假定一个float型数125.5

1.*125的二进制表示形式为01111101,小数部分0.5表示为2^-1,用二进制表示也就是 .1,那么合起来就是01111101.1,这样一来我们使用上面的公式来表示的话就是**125.5 == 1.1111011 2 ^ 6,N = 6

2.得到阶码为6,加上float型规定偏移量127,为133 == 10000101

3.得完了阶码,求尾数,将整数部分去掉得到 1111011,尾数有23位,不足的地方补0,即是1111011 00000000 00000000

4.这是一个正数,取符号位0

结合以上得到的数据,这个125.5的二进制表示形式为:

0     10000101     1111011 00000000 00000000
31    30 ~ 23             22  ~  0
它在内存中存放的形式为小端字节序即:
00000000   00000000   11111011   01000010

我们可以这么记大小端字节序,低位数据放在低位地址就是小端,低位数据放在高位地址就是大端。即:低位数据在哪(大小端)一端,就对应大小端。

4.根据二进制表示形式计算对应的浮点数:

假设浮点数为  01000010   11111011   00000000    00000000

1.首位是0,这是一个正数

2.阶码是(1000010 == 133) - 127 == 6 == N

3.尾数为1111011 00000000 00000000,得到0.1111011,加上整数部分恒为1,得到1.1111011 == M

4. S = M * 2 ^ N == 1.1111011 * 2 ^ 6,二进制,小数点向右移动6位,最终得到两部分,1111101.0 == 2 ^ 7 - 2 ^ 1 +2 ^ -1 == 125 + 0.5 == 125.5

还存在一种情况,当float型数没有整数部分时候,如0.5的表示,稍微有点不同

要构建上面的等式S = M * 2 ^ N,而M的整数部分恒为1,所以这个0.5 == 2 ^ -1,也就是0.1,为了保证整数部分为1,这时候不能向左边移动了,向右移动一位,得到1.0 ,N == -1 + 127 == 126 == 01111110,得到了N,1.0去掉整数部分就是0了,给它补齐23位,就是23个0,这是个正数,所以最后的结果是:

0  01111110  0000000   00000000  00000000

double类型的数据也是类似,计算时不同的是阶码要换成11位偏移量是1023尾数52位

在下面的网站中还有更详细的测试,用一个char型指针分别指向一个float变量的4个字节,如125.5按照在内存中存储的格式是00000000 00000000 11111011 01000010,就是 0 0 -5 66 ,第三位char是单字符型,范围-128~127

二进制在内存中是以补码的形式储存的

前面两位是0,第三位是负数,负数的补码形式是将其绝对值的二进制(就是除去符号位的其他位数)形式按位求反再加1,so对后7位取反再+1,得到5,加上负号,得到-5
第四位是0开头,正数,由于正数的补码和其原码形式相同,直接求后七位得到66

参考资料:
http://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html

总结:

    不同机器上字节序的规定
    公式:S = M * 2 ^ N
    二进制在内存中是以补码的形式存储,负数要对其二进制绝对值按位取反再加一,正数的补码和原码形式相同
    float/double类型的范围和精度的计算方式
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值