Title: Compare floating-point values safely in C#
The computer stores values, including floating-point values, in binary using 0s and 1s. That means it cannot store all possible decimal values exactly. Sometimes when you multiply or divide two floating-point values, the computer is unable to store the result exactly.
Usually this is no big deal, but you should be aware that this can happen. In particular, when you compare two values to see if they are equal, you cannot simply use == to compare them because rounding errors may make them different when they should be the same. Instead, subtract the two values and see if the result is close to 0.
For example, consider the following calculation.
float A = 5.7f;
float B = 12f;
float A_times_B = A * B;
txtAtimesB.Text = A_times_B.ToString();
The value A_times_B should be 68.4 but, due to the way the computer stores floating-point values, the result is slightly different. If a program uses == to compare the result to 68.4, the result is false.
Instead you should subtract the result from the value 68.4 and see if the difference is (in absolute value) close to 0.
This example uses the following code to demonstrate this technique.
float A = 5.7f;
float B = 12f;
float A_times_B = A * B;
txtAtimesB.Text = A_times_B.ToString();
bool equals1 = (A_times_B == 68.4f);
txtEquals1.Text = equals1.ToString();
bool equals2 = Math.Abs(A_times_B - 68.4f) < 0.00001;
txtEquals2.Text = equals2.ToString();
If you look at the picture at the beginning of the post, you'll see that the computer displays the product as 68.39999 instead of 68.4. (Even this may be slightly different from the way the computer stores the value internally. This is just the decimal representation of the binary value stored by the computer.)
The picture shows that the == test decided that the result was not equal to 68.4. The test Math.Abs(A_times_B - 68.4f) < 0.00001 correctly determined that the product was close to 68.4.
How close the difference must be to 0 depends on the calculation. In this example, 0.00001 works. If you perform a long series of calculations, rounding errors may accumulate and the result may be farther from what you expect it to be, so you may need to use another value such as 0.001.
Download the example to experiment with it and to see additional details.
|