码迷,mamicode.com
首页 > 其他好文 > 详细

浮点数在计算机中的表示

时间:2014-04-30 22:18:38      阅读:403      评论:0      收藏:0      [点我收藏+]

标签:浮点数   ieee754   计算机   表示   c语言   

先引入一道题:

Float与“零值”如何比较?

当然不能用

if(f == 0)

之类的比较~!


参考答案:

Const float EPSINON = 0.00001;

If((x >= -EPSINON)&&(x <=EPSINON))


首先,他提醒了我起名字问题,这个词儿还真没怎么用过,为了更专业,我们还是多学俩但词儿吧,那么,看看EPSINON含义——其实,他拼错了,是episilon,e么,指数么,上大学肯定都有印象,各理工科经常提及的希腊字母:

Ε ε epsilon ep`silon 伊普西龙

其次,浮点数,比如float,有二十几位的真值,我比小数点后几位合适?太多位的话会不会出差错?他本来就不是严格的“0”~!


又想起来一个问题,float double等等,反正就是32位,64位(还有更高么?)等等,具体分布,比如第一位是符号位,然后五六位是指数级,其余是“真值”——我该怎么叫他来着。。

 

其实这个题没什么好分析的,只是引入一下浮点数的概念,下边自己编了一个小程序:

mamicode.com,码迷


输出:

1.234000

address of f1 is 0xbfa00510,and the value is 1.234000

首先,给结构体f1中的f1变量赋值并打印输出来测试实际值

address of fp1 is 0xbfa00510,and the value is 1.234000

然后,是“脱了裤子放屁”,把结构体强制转换给浮点指针,因为结构体里存的也是一个浮点数,地址又相同,所以输出结果是一样的。

address of cp1 is 0xbfa00510,and the value is ffffffb6
address of cp1 + 1 is 0xbfa00511,and the value is fffffff3
address of cp1 + 2 is 0xbfa00512,and the value is ffffff9d
address of cp1 + 3 is 0xbfa00513,and the value is 3f

然后就是拆解了,通过下方的int和上方的char打印结果,可以看到f1.f1在内存中实际存储的样子(小端存储,低地址存放低位值),打印char类型会自动在前边补1(化成16进制,假如足够4位,即一个 f)
address of ip1 is 0xbfa00510,and the value is 3f9df3b6

那么这个0x3f9df3b6和1.234000 有什么关系呢?

先拆成2进制看看。

按地址,大--->小:

3          f           9       d       f        3          b       6

0011 1111 1001 1101 1111 0011 1011 0110

这个就很抽象了~!

那怎么解释呢,这就要提到浮点数在计算机中的储存格式了。如果说通常的整型更符合我们对于数据本该有的形式。浮点型更像是一个组合结构体,位结构体,这也就是我在代码中使用了一个struct的原因(只是没有真的按浮点数格式去按位拆解)。


提到浮点数,就想起《计算机组成原理》,就不得不提一个标准,IEEE754(我们现在用的是什么呢?就是IEEE754~~!当然,只有32位模式有强制要求,其他都是选择性的。大部分编程语言都有提供IEEE浮点数格式与算术,但有些将其列为非必需的。例如,IEEE754问世之前就有的C语言,现在有包括IEEE算术,但不算作强制要求(C语言的float通常是指IEEE单精确度,而double是指双精确度)。)

IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80比特实做)。

各精度的位数分配分别为:

单精度:总共32位,最大1位是符号位,其次8位是幂指数,然后就是23位的真值。单精度的指数部分是?126~+127加上偏移值127,指数值的大小从1~254(0和255是特殊值)。

双精度:总共64位,最大1位是符号位,其次11位是幂指数,然后就是52位的真值。双精度的指数部分是?1022~+1023加上1023,指数值的大小从1~2046(0(2进位全为0)和2047(2进位全为1)是特殊值)。

长精度:总共80位,忘记了,真值大概六十几位,也不常见。。。

单精度、双精度、强调一个精度嘛,主要还是真值,指数增加的不是很多(因为也没必要那么大了,太大了)。

 


先看一下我们用的,按理说是IEEE754单精度,来分析一下;

float总共32位,最大1位是符号位,其次8位是幂指数,然后就是23位的真值。

PS:浮点数的指数还不“直接”是指数,应该是移码。

8位,移码,127+127=254,254为2的八次幂,超了。最大为127次幂

最小为-127次幂,加上127为0.


那么我们来算算例子中是不是如此:

0011 1111 1001 1101 1111 0011 1011 0110

0   01111111 00111011111001110110110

该浮点数为正数,阶码为01111111,尾数部分为00111011111001110110110。因为在IEEE754中,单精度浮点数有规格化处理,所以其真正尾数部分为1.00111011111001110110110,其中‘.’为小数点。

阶码移码的01111111表示0(127-0 = 127),相当于没偏移(就是1.234嘛),所以尾数部分的小数点不用移动即可得到真实的数据。

真实数据就是:1.00111011111001110110110,其十进制值为:

1 + 1/8 + 1/16 + 1/32 + 1/128 + 1/256 + 1/512 + 1/1024 + 1/2048 + 1/2^14 + 1/2^15 + 1/2^16 + 1/2^18 + 1/2^19 + 1/2^21 + 1/2^22 ~=1.234


虽然顺手编了这个个不具代表性的浮点数——1.234,完全不用偏移,但是原理是一样的,到时候只要按偏移位数移动小数点,就能算出所需值了。

时间关系,double和更长精度的都没有去探索,有兴趣的可以自己试试。关于正负无穷数,“0”等的表达,也可以直接搜寻计算机组成原理的浮点数部分,或者直接找IEEE754的相关资料。


浮点数的偏移特性能让它表达非常广的数值范围,但是也有局限性,如果两个数的幂次不一样,你是不可能把它们“换算”成同等数量级进行直接运算的,必须要有精度损失。

举个通俗易懂的例子,一个数,表示大于0的23位数,又一个数是小数点后22位,你如何进行他们的减法?“换算呗”。但是计算机不是人,他没有笔和纸,只有寄存器。没有办法换算成功,让你乘上幂数,使两数达到同一“数量级”,因为整数部分23位,小数部分22位,加一块45位了,假如是32位的计算单元(寄存器),明显不能把他们放进去进行无损精度的减法,so...



当然,我不是说浮点数计算就没办法了,我只是说计算机的底层实现能力有限,你在上层通过一些技巧,在高级语言部分,总有办法让他无损计算的,只不过是慢点,效率低点。

 



浮点数在计算机中的表示

标签:浮点数   ieee754   计算机   表示   c语言   

原文地址:http://blog.csdn.net/huqinwei987/article/details/24784857

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!