• 浮点数问题


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

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

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

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




    上面就是常用浮点数的表示了,通常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):

    其实说白了,就是直接利用了精度的那23位表示整数,注意是整数,23位无符号整数可表示为0-2^23-1,因为是表示的整数,尽量让小数点到最后,所以肯定可以精确表示这个范围的整数。但是如果表示小数,例如0.4都不能精确表示。0.4=0.5*0+0.25*1+.......无穷尽也。注意是连续整数,不是连续整数能表示的要大的多。比如double可以表示10的30次方,整数的话可以表示很大,但不一定连续
  • 相关阅读:
    类加载机制深度解析
    Mysql索引数据结构详解(1)
    深入理解mysql锁与事务隔离级别
    关于redis HSCAN count参数不生效的问题
    在idea的java开发中字符串length()方法获取长度与赋值不符的问题
    在网页中使用超链接来打开本地应用(可传参数)
    断言(assert)简介
    9. Palindrome Number
    四、MapReduce
    三、HDFS——Hadoop分布式文件系统
  • 原文地址:https://www.cnblogs.com/zmlctt/p/3943375.html
Copyright © 2020-2023  润新知