开发者

How to make 100.02f - 100 == 0.02f being true in c#?

开发者 https://www.devze.com 2023-04-10 01:38 出处:网络
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开发

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号