【问题标题】:Why IEEE754 single-precision float has only 7 digit precision?为什么 IEEE754 单精度浮点数只有 7 位精度?
【发布时间】:2013-10-02 05:16:07
【问题描述】:

为什么单精度浮点数有 7 位精度(或双精度 15-16 位)?

谁能解释一下我们是如何根据分配给 float(Sign(32) Exponent(30-23), Fraction (22-0)) 的 32 位得出的?

【问题讨论】:

    标签: types floating-point precision ieee-754 single-precision


    【解决方案1】:

    有效数字的 23 个小数位 (22-0) 出现在内存格式中,但总精度实际上是 24 位,因为我们假设有一个前导 1。这相当于 log10(2^24) ≈ 7.225 十进制数字。

    双精度浮点数有 52 位小数,加上前导 1 是 53。因此双精度可以容纳 log10(2^53) ≈ 15.955 十进制数字,而不是 16。

    注意:前导 1 不是符号位。它实际上是 (-1)^sign * 1.ffffffff * 2^(eeee-constant) 但我们不需要将前导 1 存储在分数中。符号位仍然必须存储


    有些数字不能表示为 2 的幂和,例如 1/9:

    >>>> double d = 0.111111111111111;
    >>>> System.out.println(d + "\n" + d*10);
    0.111111111111111
    1.1111111111111098
    

    如果财务程序在没有自我纠正的情况下一遍又一遍地进行此计算,最终会出现差异。

    >>>> double d = 0.111111111111111;
    >>>> double sum = 0;
    >>>> for(int i=0; i<1000000000; i++) {sum+=d;}
    >>>> System.out.println(sum);
    111111108.91914201
    

    总计 10 亿次后,我们损失了超过 2 美元。

    【讨论】:

    • 前导 1 不是符号位。它实际上是(-1)^sign * 1.ffffffff * 2^(eeee-constant),但我们不需要将前导 1 存储在分数中。符号位仍然必须存储
    • 我在一些地方看到他们提到了 float (15 - 16 ) 的精度。曾经 15.955 会是 16 吗?
    • @jb_2519 如 Ron 所示,双精度浮点有 15.955 个 十进制 位精度。这意味着您可以很好地依赖前 15 个 decimal 数字是准确的,任何后续数字最多只能部分表示。就我个人而言,我不会依赖第 14 位(或单精度中的第 6 位)十进制数字的准确性。
    • @RonE 为什么我们采用以 10 为底的对数来计算编号。十进制数字?你能解释一下这个概念吗?
    • @PankajMahato 这就是你计算它的方式。例如,如果我们想表示以 10 为底的数字 2^24,它是 16777216。由于 log10(2^24) = 7.225,我们可以看到这应该是一个前导数字,后跟 7。反过来,如果我们想看看有 8 个十进制数字的最小二进制数是多少,我们计算如下:log2(10^8)= 26.58。因此,我们需要一个 27 位二进制数来获得具有前导数字后跟 8 位(总共 9 位)的十进制数。请记住,10^8 是一个 1 后跟 8 个零,总共 9 个数字。
    【解决方案2】:

    32 float 有 23 位,所以最小单位是

    2^(-23) = 0.00000011920928955078125
    

    其他数字只大于0.00000011920928955078125。小于0.00000011920928955078125也不是不可能。其他数字是0.00000011920928955078125组成

    0.00000011920928955078125 * n
    

    所以我们可以很容易地表示0.00000x[1-9]。而float32当然可以有6位精度。不要考虑四舍五入,我们可以计算7位数字如下:

    0.00000011920928955078125 * 1 = 0.0000001
    0.00000011920928955078125 * 2 = 0.0000002
    0.00000011920928955078125 * 3 = 0.0000003
    0.00000011920928955078125 * 4 = 0.0000004
    0.00000011920928955078125 * 5 = 0.0000005
    0.00000011920928955078125 * 6 = 0.0000007
    0.00000011920928955078125 * 7 = 0.0000008
    0.00000011920928955078125 * 8 = 0.0000009
    0.00000011920928955078125 * 9 = 0.000001
    

    它不能表示0.0000006。这是float32具有6~7位精度的结果,我们可以在互联网上到处找到。

    【讨论】:

      猜你喜欢
      • 2013-01-03
      • 2020-11-12
      • 2020-02-03
      • 2020-09-26
      • 2018-02-23
      • 2010-10-22
      • 2020-05-28
      • 2012-02-28
      • 2013-04-16
      相关资源
      最近更新 更多