... 1000 100 10 1 1/10 1/100 ...
在二进制中,它们将会是:
... 8 4 2 1 1/2 1/4 1/8 ...
这些数字也没有任何限制。数字的位置从左到右无限增加。
... 1000 100 10 1 1/10 1/100 ...
在二进制中,它们将会是:
... 8 4 2 1 1/2 1/4 1/8 ...
这些数字也没有任何限制。数字的位置从左到右无限增加。
2^x = y ;
x = log(y) / log(2)
2^1, 2^0, 2^(log(1/2) / log(2)), 2^(log(1/4) / log(2)), 2^(log(1/8) / log(2)),2^(log(1/16) / log(2)) ........
这可能能够解决问题,所以如果你想要将32.41写成二进制,那么它应该是:
2^5 + 2^(log(0.4) / log(2)) + 2^(log(0.01) / log(2))
或者
2^5 + 2^(log(0.41) / log(2))
float a = 60;
float b = 0.1;
float c = a + b * 10;
c的值是多少?它并不完全等于61,因为b实际上并不是0.1,因为0.1在二进制中没有精确的表示。
数字61.0确实具有精确的浮点运算,但并非对于所有整数都是如此。如果您编写了一个循环,将双精度浮点数和64位整数都加1,最终会达到一个点,其中64位整数完美地表示了一个数字,但浮点数却没有,因为它没有足够的有效位。
在小数点右侧,接近值的点就容易得多。如果开始用二进制浮点数写出所有数字,这就更有意义了。
另一种思考方式是,当您注意到数字61.0在十进制中可以完美表示时,并且移动小数点不会改变这一点,您正在执行10的乘方(10^1,10^-1)乘法。在浮点数中,乘以2的幂不会影响数字的精度。尝试重复将61.0除以3,以说明一个完全准确的数字如何失去其精确表示。
这里有一个阈值,因为数字的含义已经从整数变成了非整数。要表示61,您需要6*10^1 + 1*10^0;10^1和10^0都是整数。6.1是6*10^0 + 1*10^-1,但10^-1是1/10,绝对不是整数。这就是你最终进入Inexactville的原因。
你无法在二进制中精确地表示0.1,就像你无法使用传统的英寸标尺来测量十分之一英寸一样。
英寸标尺和二进制小数都是关于一半的。你可以测量半英寸、四分之一英寸(当然是半个半英寸)、八分之一英寸、十六分之一英寸等。
但如果你想要精确地测量十分之一英寸,那么你就没那么幸运了。它比八分之一英寸少,但比十六分之一英寸多。如果你想得更准确,你会发现它比3/32略大一点,但比7/64略小一点。我从未见过实际上有比64份之一还细的刻度的标尺,但如果你做一下数学,你会发现1/10比13/128小,而比25/256大,并且比51/512大。你可以继续用1024分之一、2048分之一、4096分之一、8192分之一等更细的单位来测量,但是即使在一个无限细的基于二的标尺上,你也永远找不到与1/10或0.1完全对应的明确标记。
你会发现一些有趣的东西。让我们来看看我列出的所有近似值,并为每个值明确记录0.1是更小还是更大:
分数 | 小数 | 0.1 是... | 转化为 0/1 |
---|---|---|---|
1/2 | 0.5 | 小于 | 0 |
1/4 | 0.25 | 小于 | 0 |
1/8 | 0.125 | 小于 | 0 |
1/16 | 0.0625 | 大于 | 1 |
3/32 | 0.09375 | 大于 | 1 |
7/64 | 0.109375 | 小于 | 0 |
13/128 | 0.1015625 | 小于 | 0 |
25/256 | 0.09765625 | 大于 | 1 |
51/512 | 0.099609375 | 大于 | 1 |
103/1024 | 0.1005859375 | 小于 | 0 |
205/2048 | 0.10009765625 | 小于 | 0 |
409/4096 | 0.099853515625 | 大于 | 1 |
819/8192 | 0.0999755859375 | 大于 | 1 |
0001100110011
。这并不是巧合,无限重复的二进制分数1/10就是0.0001100110011...正如我们一直在讨论的那样,在浮点算术中,十进制数0.1无法在二进制中完美表示。
浮点和整数表示为所表示数字提供了网格或晶格。随着算术运算的进行,结果会从网格上掉落,并且必须通过四舍五入将其放回到网格上。例如,在二进制网格上的1/10。
如果我们使用二进制编码的十进制表示法,就像有位先生建议的那样,我们是否能够将数字保持在网格上?
有无限数量的有理数,但是只有有限位来表示它们。请参见http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems。
你知道整数吧?每个位代表2^n。
2^4=16
2^3=8
2^2=4
2^1=2
2^0=1
对于浮点数也是一样的(有些区别),但是位代表2^-n。
2^-1=1/2=0.5
2^-2=1/(2*2)=0.25
2^-3=0.125
2^-4=0.0625
浮点二进制表示:
符号 指数 小数(我认为小数后面会添加一个看不见的1)
B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0
上面得分很高的答案说得很好。
首先,在你的问题中混合了二进制和十进制,然后当你在右侧放置一个不能被基数整除的数字时,就会出现问题。比如十进制中的1/3,因为3不能被10的幂整除,或者二进制中的1/5,它不能被2的幂整除。
另外,永远不要在浮点数中使用等号,即使它是一个精确的表示,某些浮点系统中的一些数字可以用多种方式准确地表示(IEEE在这方面做得很糟糕,它是一个可怕的浮点规范,所以请预料头痛)。在这里也是一样,1/3不等于计算器上的0.3333333,无论小数点右边有多少个3。它可能足够接近,但并不相等。因此,你会期望像2*1/3这样的表达式不等于2/3,具体取决于四舍五入。永远不要在浮点数中使用等号。