你不能做以 10 为基础的事情并假设它们以相同的方式在以 2 为基础工作。
双精度 IEEE
0.1 = 0x3FB999999999999A
3.0 = 0x4008000000000000
12.34567 = 0x4028B0FBA8826AA9
0.1*3.0 = 0x3FD3333333333334
(0.1*3.0)/3.0 = 0x3FB999999999999B
单在计算器上更容易处理,并注意有趣的区别:
0.1 = 0x3DCCCCCD
3.0 = 0x40400000
12.34567 = 0x414587DD
0.1*3.0 = 0x3E99999A
(0.1*3.0)/3.0 = 0x3DCCCCCD
所以首先
0x3DCCCCCD is 0 01111011 10011001100110011001101
如果分母 1/3 = 0.3333333 中有一个 3,请注意与以十为底的重复模式。就像 1/6 0.16666667 因为我们四舍五入。好吧,看看最后一点,它最后会是 1001,但这有点太多了,如果你要砍掉的点之后的数字大于你四舍五入的一半,那么二进制中的 0.1001 舍入到 0.101是的?同样的交易。
在这种情况下,对于您的十进制数字,单精度得出正确答案,将某个数字乘以 3,然后再除以得到相同的数字,但在不同点的舍入剪辑加倍时,我们再次四舍五入并最终得到的数字比开始时要大得多。
这一切都可以很容易地以十进制形式显示。如果我的格式是固定位数,我必须在某个点停止,所以可以说 1/6 = 0.166666 或者它是 0.166667。和 6.0 可以说是 6.00000。因此,如果我使用十进制浮点格式并乘以 6 * (1/6),我得到 0.99996 或 1.000002 在这两种情况下都不会得到 1。不是因为四舍五入,而是因为数字无法以该格式准确表示。
如果您从某个以 10 为基数的 ASCII 字符串变为浮点数,然后又回到某个以 10 为基数的 ASCII 字符串时,如果您恢复了开始时的数字,那么这只是运气。该数字要么以浮点数准确表示,要么没有。您可以通过上面非常简单的以 10 为底的浮点数看到,无论您有多少位接近无穷大,您都不会得到 6 * (1/6) = 1,因为以 10 为底的浮点数不能准确地表示 1/6固定位数。
查看你的其他号码
12.34567 = 0x414587DD
0 10000010 10001011000011111011101
12.34567 = 0x4028B0FBA8826AA9
0 10000000010 1000101100001111101110101000100000100110101010101001
1.10001011000011111011101
1.1000101100001111101110101000100000100110101010101001
很明显 single 没有足够的位来表示它,并且没有向上舍入,因为下一位是小于一半的零。并且双打一直工作到最后,我不会将它转换回以 10 为底的数字,但我愿意打赌你只是走运了。如果你有更多的比特,那会安定下来吗?同样,我不会为您手动转换。我认为您应该能够看到,即使您只是查看 0.1 并转到浮动并返回 ASCII,您也不会得到 0.1。就像以十进制为基础的 1/6 不会在那里和回来转换,如果你将它四舍五入,你会很幸运:5.9999... 如果你在正确的位置剪辑/四舍五入,则四舍五入为 6.0,但这只是 ASCII 转换的四舍五入而不是浮点格式表示的实际数字。