Of course, you should never compare floating point values โโthat are the result of a calculation for equality, but always use a small tolerance, for example:
double value1 = ... double value2 = ... if (Math.Abs(value1 - value2) < tolerance * Math.Abs(value1)) { ... values are close enough }
But if I use Math.Round, I can always be sure that the resulting value will be consistent, i.e. will the next Assert always be executed, even if the rounded value is a value that cannot be represented exactly double?
public static void TestRound(double value1, double value2, int decimals) { double roundedValue1 = Math.Round(value1, decimals); double roundedValue2 = Math.Round(value2, decimals); string format = "N" + decimals.ToString(); if (roundedValue1.ToString(format) == roundedValue2.ToString(format)) {
If not, please provide a counterexample.
EDIT
Thanks to the expert for a counterexample created by brute force, which proves that the result is not "consistent" in the general case. This counterexample contains 16 significant digits in a rounded result - it also fails in the same way when it scales in this way:
double value1 = 10546080000034341D; double value2 = 10546080000034257D; int decimals = 0; TestRound(value1, value2, decimals);
However, I would also be interested in a more mathematical explanation. Bonus bonuses for any of the more mathematical Stackoverflowers that can perform any of the following actions:
Find a counterexample where a rounded result has less than 16 significant digits.
Define a range of values โโfor which the rounded result will always be โconsistentโ as defined here (for example, all values โโin which the number of significant digits in the rounded result is <N).
Provide an algorithmic method for creating counterexamples.
source share