任何人都可以向我解释为什么这个程序:
for(float i = -1; i < 1; i += .1F)
Console.WriteLine(i);
输出:
-1
-0.9
-0.8
-0.6999999
-0.5999999
-0.4999999
-0.3999999
-0.2999999
-0.1999999
-0.99999993
7.450581E-08
0.1000001
0.2000001
0.3000001
0.4000001
0.5000001
0.6000001
0.7000001
0.8000001
0.9000002
舍入错误来自哪里?
答案 0 :(得分:3)
浮点数不正确,它们总是近似的,因为它们必须是圆形的!
它们在二进制表示中是精确的
每个CPU或PC都可能导致不同的结果
看看Wikipedia page
答案 1 :(得分:3)
我确信这个问题之前一定是以某种形式提出过的,但我很快就找不到了。 :)
答案归结为表示浮点数的方式。您可以进入technical detail via wikipedia,但只是说十进制数不一定具有精确的浮点表示...
浮点数(无论如何像双打和浮点数一样,基数2浮点数)工作[0]的方法是将1/2的幂加起来得到你想要的。所以0.5只是1/2。 0.75是1/2 + 1/4,依此类推。
问题在于,你不能在这个二进制系统中代表0.1,如果没有2个越来越小的幂的无限流,那么计算机能做的最好就是存储一个非常接近但不是很接近0.1的数字。
通常你没有注意到这些差异,但它们存在,有时你可以让它们自己显现出来。有很多方法可以解决这些问题,你使用哪种方法很大程度上取决于你实际使用它的方式。
[0]略微手持式接近
答案 2 :(得分:2)
最大的问题是0.1
无法用二进制表示,就像1 / 3
或1 / 7
无法用十进制表示一样。因此,由于计算机必须在某个时刻切断,因此会累积舍入错误。
尝试使用几乎任何编程语言执行0.1 + 0.7 == 0.8
,结果会导致错误。
在C#中解决此问题,请使用decimal
类型以获得更好的精确度。
答案 3 :(得分:2)
答案 4 :(得分:1)
舍入错误来自Float不是精确数据类型(转换为十进制)时的事实,它是一个近似值,注意C# Reference Float被指定为具有7位小数精度。< / p>
答案 5 :(得分:1)
任何浮点变量都是基础。原因很复杂,但是如果你谷歌的话,有很多信息。
请尝试使用Decimal。
答案 6 :(得分:1)
正如其他海报所暗示的那样,问题源于浮点数是精确的十进制表示的假设。它们不是 - 它们是数字的精确 二进制 (base-2)表示。您遇到的问题是您不能总是以十进制格式表示精确的二进制数 - 就像您不能以十进制格式表示1/3(.33333333 ...)。在某些时候,必须进行舍入。
在您的示例中,当您表达.1F时会发生舍入(因为这不是可以在base-2中精确表示的值)。