首页 > 其他 > 详细

浮点数问题

时间:2014-08-28 23:59:56      阅读:578      评论:0      收藏:0      [点我收藏+]

(1)浮点数是有理数的集合,有些有理数不能表示,会有舍去误差如0.1等。

 

(2)浮点数可以表示的连续整数也是有限的。

有些脚本语言,比如awk,lua中都是使用浮点数来存储整数的,也就是说,我们在语言中使用的整数,在语言内部是使用浮点数来表示的。我们知道,浮点数的运算中通常存在着一定的误差,所以整数是否能被浮点数精确表示呢?答案是可以,不过不是所有范围的整数都可以被精确的表示。由于浮点数精度的问题,所以浮点数的分布也就呈现出非均匀分布。

先简单介绍一下一个常用的浮点数在计算机中的组成,最常用的浮点数表示法是IEEE754标准,对于这个标准,可以参考[1]


bubuko.com,布布扣

上面就是常用浮点数的表示了,通常sign占用1bit,对于单精度浮点数exponent占用8bits,significand占用23bits。由于IEEE754使用规格化浮点数,所以尾数的最高位必然为1,所以没必要存储,于是有一个隐藏位(hidden bit),所以尾数真正的有效位数为24bits。有兴趣的读者可以参考[1],其中有详细介绍。

 

当用浮点数来表示整数时,我们要得到连续的整数分布,肯定希望尾数的精度越高越好。很显然,尾数位数有限制,也就限制了能表示的最大的整数的值。对于一个浮点数,设p为其尾数的有效位数(这里p包含一个hidden bit),那么最大的尾数就是1 + 1 - 2^(-p+1),所以最大的整数为(2-2^(-p+1)) * 2^(p-1) = 2^p - 1。由于浮点数是有符号的,所以很自然的我们想到整数范围为[-2^p – 1, 2^p – 1]。可是我们还遗漏了2个数,就是2^p和-2^p。我们来看这两个整数的浮点数表示。规格化后,2^p = (1.0000…000) * 2^p,其中尾数部分小数点后有p个0。但是我们知道,我们的尾数最多只能存储p - 1个,其中一个是hidden bit,但是很巧,由于被舍去的最后一个数字是0,所以不影响实际取值,所以2^p就可以精确表示了。同理-2^p也是如此。

注意,可能有读者会想到,既然1.00..000*2^p可以精确表示,那么很显然,对于单精度浮点数p=24,而指数的可表示范围远大于24,是8-bit,也就是可以到达+127,那么为什么2^p就是可以表示的最大整数呢。因为我们只关心连续的整数范围,2^(p+1)的确可以精确表示,但是[2^p, 2^(p+1)]之间还有许多数就无法表示了,因为尾数不够。

所以对于IEEE754 单精度和双精度浮点数,能够精确表示的整数的范围为

Floating point Range
Single precision [-2^24, 2^24]
Double precision [-2^53, 2^53]

以下代码测试了一下两种浮点数的边界条件(运行环境为VC9):

    1. #include <cassert>  
    2.   
    3. int main()  
    4. {  
    5.     const int max_decimal = 16777216; // 2^24  
    6.     assert(static_cast<int>(static_cast<float>(max_decimal)) == max_decimal);  
    7.     assert(static_cast<int>(static_cast<float>(max_decimal + 1)) != max_decimal + 1);  
    8.   
    9.     assert(static_cast<int>(static_cast<float>(-max_decimal)) == -max_decimal);  
    10.     assert(static_cast<int>(static_cast<float>(-max_decimal - 1)) != -max_decimal - 1);  
    11.   
    12.     const __int64 max_decimald = 9007199254740992; // 2^53  
    13.     assert(static_cast<__int64>(static_cast<double>(max_decimald)) == max_decimald);  
    14.     assert(static_cast<__int64>(static_cast<double>(max_decimald + 1)) != max_decimald + 1);  
    15.   
    16.     assert(static_cast<__int64>(static_cast<double>(-max_decimald)) == -max_decimald);  
    17.     assert(static_cast<__int64>(static_cast<double>(-max_decimald - 1)) != -max_decimald - 1);  
    18. }  

浮点数问题

原文:http://www.cnblogs.com/zmlctt/p/3943375.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!