Good day!

The following question arose: for example, we have a double variable and some accuracy (precition variable), which will determine the number of decimal places of interest:

double x = 9.3813020199999; double precition = 0.001; 

Knowing the above data, we need to get the exact number 9.381 (and without extra zeros at the end). Is there a way to do this?

UPD I need to test the Sqrt method (code below) and I don’t know how to properly write a test for NUnit if the method returns a double. After all, we should have an expected-value that is compared with the return value of the method.

  public static double Sqrt(double x, int n, double precition) { if (x < 0 && n % 2 == 0) throw new ArgumentException(); double result = x / n; double previousResult; do { previousResult = result; result = ((double)1 / n) * ((n - 1) * previousResult + (x / Sqr(previousResult, n - 1))); } while (Math.Abs(result - previousResult) > precition); return result; } 

So far, my testing method, written using NUnit, looks like this:

  [TestFixture] public class NewtonSqrtTests { [TestCase(4, 2, 0.001, ExpectedResult = 2.000)] [TestCase(27, 3, 0.0001, ExpectedResult = 3.0000)] [TestCase(88, 2, 0.001, ExpectedResult = 9.380)] [TestCase(81, 2, 0.001, ExpectedResult = 9.000)] public double Sqrt_PositiveTest(double x, int n, double precition) { return NewtonSqrt.Sqrt(x, n, precition); } } 
  • Do you think that precition is exactly 0.001? Not so: ideone.com/TgKjVj - VladD
  • That's not the point. This number only indicates how many decimal places I need. I can use the number 3 instead of the number 0.001. - Andrei Khotko
  • In this, in this. The 9.381 number you want to get is just as unrepresentable in the double type. - VladD

1 answer 1

If we talk about decimals, then it is meaningless to remain within the double type: in it you cannot express your required accuracy exactly. For example, because in the double type it is impossible to express accurately neither the number 0.001, nor the number 9.381. ( illustration related response )

You need to go to the type decimal , which is specifically for this purpose.

 double x = 9.3813020199999; decimal precision = 0.001m; decimal result = Math.Round((decimal)x / precision) * precision; // 9.381 

If the number of decimal places is known as a number, it can be easier:

 double x = 9.3813020199999; decimal result = Math.Round((decimal)x, 3); // 9.381 

Update: If you stay within the double type, you cannot compare them: the equality of theoretically identical double numbers, calculated in different ways, is almost an incredible event due to rounding errors. In such cases, approximate equality is used up to epsilon . For example, in NUnit there are special functions for such purposes:

Values ​​of type of float and double are modulated.

  • I updated the question. In the unit test, I need to compare expected with actual. But since the method returns a double (this is a necessary condition of the task, I cannot replace it with a decimal), I cannot correctly compare the expected with the actual. Maybe you have ideas for solving this problem? - Andrei Khotko
  • @AndreiKhotko: Updated the answer, look. - VladD
  • Thank you for the answer, this is what you need!) - Andrei Khotko
  • @AndreiKhotko: It seems impossible to achieve this with an ExpectedResult , so you have to rewrite the tests a bit, passing the expected value inward. - VladD
  • yes, you just need to remove ExpectedResult, make a void method and make the necessary Assert inside - Andrei Khotko