【发布时间】:2010-02-08 22:52:10
【问题描述】:
我正在为一位同事写一个有启发性的示例,向他展示为什么测试浮点数的相等性通常是一个坏主意。我使用的示例是添加 0.1 十次,并与 1.0(我在介绍性数字课程中展示的那个)进行比较。我惊讶地发现这两个结果相等 (code + output)。
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
一些调查表明,这个结果不能被依赖(很像浮动平等)。我发现最令人惊讶的是,添加代码在其他代码之后可能会改变计算结果 (code + output)。请注意,此示例的代码和 IL 完全相同,只是多了一行 C#。
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
Console.WriteLine(@float.ToString("G9"));
我知道我不应该在浮点数上使用相等,因此不应该太在意这一点,但我发现这非常令人惊讶,就像我向所有人展示过的一样。 在执行计算之后做的事情会改变前面计算的值吗?我不认为这是人们通常想到的计算模型。
我并没有完全被难住,可以肯定地假设在“相等”情况下发生某种优化会改变计算结果(在调试模式下构建可以防止“相等”情况)。显然,当 CLR 发现稍后需要对浮点数进行装箱时,优化就被放弃了。
我进行了一些搜索,但找不到这种行为的原因。谁能帮我解答一下?
【问题讨论】:
-
也很有趣:如果我 fork your first example 并在没有任何更改的情况下运行它,我将不再得到您最初看到的结果。
标签: .net floating-point clr equality ieee-754