Why does a single-precision floating point number have 7 digit precision (or double 15-16 digits precision)?
Can anyone please explain how we arrive on that based on the 32 bits assigned for float(Sign(32) Exponent(30-23), Fraction (22-0))?
Why does a single-precision floating point number have 7 digit precision (or double 15-16 digits precision)?
Can anyone please explain how we arrive on that based on the 32 bits assigned for float(Sign(32) Exponent(30-23), Fraction (22-0))?
有效数字的 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 美元。
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 位精度的结果,我们可以在互联网上随处找到。