在之前做过的一个项目中遇到了小数计算不精确的问题,如下图所示

我重现了一下,大致是1.05+1+1.05// 3.0999999999999996这种的,于是看了下二进制是如何表示小数的。
简单点讲的话,就是可以类比十进制的浮点数来理解二进制的浮点数
| 十进制 | 1 | 2 | 3 | . | 5 | 8 | 9 |
| 理解方式 | 1*102 | 2*101 | 3*100 | . | 5*(1/101) | 8*(1/102) | 9*(1/10%3) |
| 二进制 | 1 | 1 | 1 | . | 1 | 0 | 1 |
| 理解方式 | 1*22 | 1*21 | 1*20 | . | 1*(1/21) | 1*(1/22) | 1*(1/23) |
因此二进制只能精确表示0.5(1/2)、0.25(1/4)、0.125(1/8)、0.0625(1/16)、…这种的小数,当然了像1.0、2.0、3.0这种的小数部分全为0的也是可以精确表示的,其他的小数均无法精确表示,所以运算结果也就可能会出现长尾,之所以有一部分不会出现长尾,参考了其他资料后可以发现是语言本身做了部分优化,过分接近的数字会被语言直接优化成看似精确的值。
| 十进制小数 | 二进制 |
|---|---|
| 0.1 | 0.0001100110011001100110011001100110011001100110011001101 |
| 0.2 | 0.001100110011001100110011001100110011001100110011001101 |
| 0.3 | 0.010011001100110011001100110011001100110011001100110011 |
| 0.4 | 0.01100110011001100110011001100110011001100110011001101 |
| 0.5 | 0.1 |
| 0.6 | 0.10011001100110011001100110011001100110011001100110011 |
| 0.7 | 0.1011001100110011001100110011001100110011001100110011 |
| 0.8 | 0.1100110011001100110011001100110011001100110011001101 |
| 0.9 | 0.11100110011001100110011001100110011001100110011001101 |
| 0.10 | 0.0001100110011001100110011001100110011001100110011001101 |
| 0.11 | 0.00011100001010001111010111000010100011110101110000101001 |
| 0.12 | 0.00011110101110000101000111101011100001010001111010111 |
| 0.13 | 0.00100001010001111010111000010100011110101110000101001 |
| 0.14 | 0.00100011110101110000101000111101011100001010001111011 |
| 0.15 | 0.0010011001100110011001100110011001100110011001100110011 |
| 0.16 | 0.0010100011110101110000101000111101011100001010001111011 |
| 0.17 | 0.0010101110000101000111101011100001010001111010111000011 |
| 0.18 | 0.001011100001010001111010111000010100011110101110000101 |
| 0.19 | 0.001100001010001111010111000010100011110101110000101001 |
| 0.20 | 0.001100110011001100110011001100110011001100110011001101 |
| 0.21 | 0.0011010111000010100011110101110000101000111101011100001 |
| 0.22 | 0.0011100001010001111010111000010100011110101110000101001 |
| 0.23 | 0.0011101011100001010001111010111000010100011110101110001 |
| 0.24 | 0.0011110101110000101000111101011100001010001111010111 |
| 0.25 | 0.01 |
| 0.26 | 0.0100001010001111010111000010100011110101110000101001 |
| 0.27 | 0.010001010001111010111000010100011110101110000101001 |
| 0.28 | 0.0100011110101110000101000111101011100001010001111011 |
| 0.29 | 0.010010100011110101110000101000111101011100001010001111 |
| 0.30 | 0.010011001100110011001100110011001100110011001100110011 |
| 0.31 | 0.010011110101110000101000111101011100001010001111010111 |
| 0.32 | 0.010100011110101110000101000111101011100001010001111011 |
| 0.33 | 0.010101000111101011100001010001111010111000010100011111 |
| 0.34 | 0.010101110000101000111101011100001010001111010111000011 |
| 0.35 | 0.01011001100110011001100110011001100110011001100110011 |
| 0.36 | 0.01011100001010001111010111000010100011110101110000101 |
| 0.37 | 0.01011110101110000101000111101011100001010001111010111 |
| 0.38 | 0.01100001010001111010111000010100011110101110000101001 |
| 0.39 | 0.01100011110101110000101000111101011100001010001111011 |
| 0.40 | 0.01100110011001100110011001100110011001100110011001101 |
| 0.41 | 0.011010001111010111000010100011110101110000101000111101 |
| 0.42 | 0.011010111000010100011110101110000101000111101011100001 |
| 0.43 | 0.011011100001010001111010111000010100011110101110000101 |
| 0.44 | 0.011100001010001111010111000010100011110101110000101001 |
| 0.45 | 0.011100110011001100110011001100110011001100110011001101 |
| 0.46 | 0.011101011100001010001111010111000010100011110101110001 |
| 0.47 | 0.0111100001010001111010111000010100011110101110000101 |
| 0.48 | 0.011110101110000101000111101011100001010001111010111 |
| 0.49 | 0.0111110101110000101000111101011100001010001111010111 |
| 0.50 | 0.1 |
| 0.51 | 0.1000001010001111010111000010100011110101110000101001 |
| 0.52 | 0.100001010001111010111000010100011110101110000101001 |
| 0.53 | 0.1000011110101110000101000111101011100001010001111011 |
| 0.54 | 0.10001010001111010111000010100011110101110000101001 |
| 0.55 | 0.1000110011001100110011001100110011001100110011001101 |
| 0.56 | 0.100011110101110000101000111101011100001010001111011 |
| 0.57 | 0.10010001111010111000010100011110101110000101000111101 |
| 0.58 | 0.10010100011110101110000101000111101011100001010001111 |
| 0.59 | 0.10010111000010100011110101110000101000111101011100001 |
| 0.60 | 0.10011001100110011001100110011001100110011001100110011 |
| 0.61 | 0.10011100001010001111010111000010100011110101110000101 |
| 0.62 | 0.10011110101110000101000111101011100001010001111010111 |
| 0.63 | 0.10100001010001111010111000010100011110101110000101001 |
| 0.64 | 0.10100011110101110000101000111101011100001010001111011 |
| 0.65 | 0.10100110011001100110011001100110011001100110011001101 |
| 0.66 | 0.10101000111101011100001010001111010111000010100011111 |
| 0.67 | 0.10101011100001010001111010111000010100011110101110001 |
| 0.68 | 0.10101110000101000111101011100001010001111010111000011 |
| 0.69 | 0.101100001010001111010111000010100011110101110000101 |
| 0.70 | 0.1011001100110011001100110011001100110011001100110011 |
| 0.71 | 0.10110101110000101000111101011100001010001111010111 |
| 0.72 | 0.1011100001010001111010111000010100011110101110000101 |
| 0.73 | 0.101110101110000101000111101011100001010001111010111 |
| 0.74 | 0.1011110101110000101000111101011100001010001111010111 |
| 0.75 | 0.11 |
| 0.76 | 0.1100001010001111010111000010100011110101110000101001 |
| 0.77 | 0.110001010001111010111000010100011110101110000101001 |
| 0.78 | 0.1100011110101110000101000111101011100001010001111011 |
| 0.79 | 0.11001010001111010111000010100011110101110000101001 |
| 0.80 | 0.1100110011001100110011001100110011001100110011001101 |
| 0.81 | 0.110011110101110000101000111101011100001010001111011 |
| 0.82 | 0.11010001111010111000010100011110101110000101000111101 |
| 0.83 | 0.11010100011110101110000101000111101011100001010001111 |
| 0.84 | 0.11010111000010100011110101110000101000111101011100001 |
| 0.85 | 0.11011001100110011001100110011001100110011001100110011 |
| 0.86 | 0.11011100001010001111010111000010100011110101110000101 |
| 0.87 | 0.11011110101110000101000111101011100001010001111010111 |
| 0.88 | 0.11100001010001111010111000010100011110101110000101001 |
| 0.89 | 0.11100011110101110000101000111101011100001010001111011 |
| 0.90 | 0.11100110011001100110011001100110011001100110011001101 |
| 0.91 | 0.11101000111101011100001010001111010111000010100011111 |
| 0.92 | 0.11101011100001010001111010111000010100011110101110001 |
| 0.93 | 0.11101110000101000111101011100001010001111010111000011 |
| 0.94 | 0.111100001010001111010111000010100011110101110000101 |
| 0.95 | 0.1111001100110011001100110011001100110011001100110011 |
| 0.96 | 0.11110101110000101000111101011100001010001111010111 |
| 0.97 | 0.1111100001010001111010111000010100011110101110000101 |
| 0.98 | 0.111110101110000101000111101011100001010001111010111 |
| 0.99 | 0.1111110101110000101000111101011100001010001111010111 |
本文深入探讨了二进制浮点数如何表示十进制小数,以及由此引发的计算不精确性问题。通过展示不同小数的二进制表示,揭示了为什么0.1加起来可能不等于0.3,原因是二进制无法精确表示某些十进制分数。此外,还提到了编程语言对近似值的优化处理。
847

被折叠的 条评论
为什么被折叠?



