1

我在一个应用程序中有一个相当奇怪的错误,我已经设法缩小到这个简单的测试用例。

protected void Page_Load(object sender, EventArgs e)
{
    bool isHeightExceeded = IsHeightExceeded(10.16f, 127.15f);
    lit.Text = isHeightExceeded.ToString();
}

private bool IsHeightExceeded(float y, float height)
{
    float nextHeight = y + height;
    return (137.31f - nextHeight) < 0;
}

当我在调试模式下构建并运行它时,isHeightExceeded bool 为 False(如我所料),但是当我在发布模式下重新构建和运行时,它现在为 True。

幕后发生了什么导致了这种情况?我猜它与浮点精度有关,但不确定是什么。

任何帮助,将不胜感激。

4

2 回答 2

4

我怀疑 10.16f + 127.15f 的值是以 64(或 80)位计算的,然后与 137.31f 进行比较......而在释放模式下,该值是计算的,然后被截断为 32 位,然后进行比较。基本上,当中间值没有被限制在较小的精度时,您可以获得这样的结果。

如果这是一个问题,那可能表明您不应该使用floatdouble开始使用 - 如果这些是精确值,请decimal改用。

于 2012-08-07T10:31:05.063 回答
1

10.16 + 127.15 正好等于 137.31,这意味着 的理论值为(137.31f - nextHeight)0。

由于涉及数值运算,您可能会遇到数值精度问题。使用调试器时,此问题的处理方式可能与不使用调试器时不同。这只是一个猜想,但我不会感到惊讶。

在任何情况下,您的代码都需要更正以解决精度错误,并使用自定义的epsilon容差值(例如,0.00001),以便为人类读者和用户提供可预测的结果。如果您不添加此容差,则代码可能仅适用于双精度值,而不适用于阅读它的人。

于 2012-08-07T10:31:51.900 回答