我正在为一位同事写一个有启发性的示例,向他展示为什么测试浮点数是否相等通常是一个坏主意。我使用的示例是添加 0.1 十次,并与 1.0(我在介绍性数字课程中展示的那个)进行比较。我惊讶地发现这两个结果是相等的(代码+输出)。
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
一些调查表明,这个结果不能被依赖(很像浮动平等)。我发现最令人惊讶的是,在其他代码之后添加代码可能会改变计算结果(代码+输出)。请注意,此示例具有完全相同的代码和 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 发现它稍后需要对浮点数进行装箱时,就会放弃优化。
我搜索了一下,但找不到这种行为的原因。任何人都可以提示我吗?