Kevin Main
Kevin Main

Reputation: 2344

bool value different when built in debug mode than in release mode

I have a rather odd bug in an application which I have managed to narrow down to this simple test case.

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;
}

When I build and run this in debug mode the isHeightExceeded bool is False (as I would expect) however when I rebuild and run in release mode it is now True.

What is happening behind the scenes to cause this? I am guessing it has something to do with floating point precision but not exactly sure what.

Any help would be appreciated.

Upvotes: 1

Views: 461

Answers (2)

Daniel Daranas
Daniel Daranas

Reputation: 22644

10.16 + 127.15 equals exactly 137.31, which means that the theoretical value of (137.31f - nextHeight) is 0.

Since there are numerical operations involved, you can incur in a numerical precision issue. It is possible that this issue is treated differently when using the debugger than when not. This is just a conjecture, but I wouldn't be surprised.

In any case, your code needs to be corrected to account for the precision error, and use a custom epsilon value of tolerance (for example, 0.00001) in order to have a predictable result for human readers and users. If you don't add this tolerance the code may work correctly just for double values, not for humans reading it.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1503290

I suspect that the value of 10.16f + 127.15f is computed in 64 (or 80) bits and then compared with 137.31f... whereas in release mode the value is computed, then truncated to 32 bits and then compared. Basically when intermediate values aren't clamped to a smaller precision, you can get results like this.

If it's an issue, that probably suggests you shouldn't be using float or double to start with - if these are meant to be precise values, use decimal instead.

Upvotes: 4

Related Questions