How to make 100.02f - 100 == 0.02f being true in c#?
It seems to be rounding problem. I have array of float[] and some operations over this array. I need to write unit tests for this functionality, but comparing expected values to the resulted values开发者_StackOverflow中文版 happened to be not a simple task taking into account this rounding issues. Is any workaround to test math operations over my array? Thanks
Rounding issues are an inherent part of floating-point calculations. Use an array of decimals (decimal[]
), perhaps?
100.02m - 100
When using floats or doubles in unit tests, your testing framework may allow you to account for an acceptable delta. Using NUnit, for example, you might write
double expected = 1d;
double delta = 0.0001d;
double actual = classUnderTest.Method();
Assert.AreEqual(expected, actual, delta);
Understand that floats and doubles are inherently imprecise for certain things, and that is by design. They represent numbers in base 2. If you need accurate base 10 representation, use the appropriate type for that: decimal
.
If you'd written 1.1 - 0.1 == 1.0
, it would still return false. It's because you're dealing with floating point numbers in a binary number system. You can't represent 0.1 in binary exactly any more than you can represent 1/3 exactly in base 10.
This is true in C#, Java, C++, C, JavaScript, Python, and every other programming language that uses the IEEE floating point standard.
You should use an "epsilon" value to check against (where epsilon is chosen by you)
if (yourvalue <= (0.02f + epsilon) && yourvalue >= (0.02f - epsilon))
// do what you want
I don't know if this is already implemented in c#, this is the "technical" approach
Obviusly the epsilon value should be enough small. Also I suggest to write an extension method to feel more comfortable when using it
Since you're writing unit tests, you can easily just compute what the exact output will be. Simply compute the output, then print it using the "roundtrip" format, and then paste that string into your unit test:
float output = Operation(array);
Console.WriteLine(output.ToString("r"));
Then you'll end up with something like Assert.AreEqual(100.02 - 100, 0.019999999999996)
Alternately, you can take the output of your unit test and convert it to a string, and then compare the string. Then you'll end up with something like:
Assert.AreEqual((100.02 - 100).ToString("f"), "0.02");
You shouldn't really compare floats for equality – you can't avoid this sort of rounding errors. Depending on your use case, either use decimals if you want rounding to be more intuitive in cases like yours, or compare the difference between the floats to a chosen "acceptable" error value.
精彩评论