Доброго времени суток!
Возник следующий вопрос: к примеру, у нас есть переменная типа double и некоторая точность (переменная precition), которая будет определять количество интересующих нас знаков после запятой:
double x = 9.3813020199999;
double precition = 0.001;
Зная вышеперечисленные данные, нам нужно получить точное число 9.381 (и без лишних нулей в конце). Есть ли способ это осуществить?
UPD Мне необходимо протестировать метод Sqrt (код ниже) и я не знаю, как правильно написать тест для NUnit, если метод возвращает число double. Ведь у нас должно быть expected-значение, которое сравнивается с возвращаемым значением метода.
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;
}
Пока мой тестирующий метод, написанный с помощью NUnit, выглядит так:
[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);
}
}
Ответ
Если говорить о десятичных знаках, то оставаться в рамках типа double бессмысленно: в нём вы не можете выразить вашу требуемую точность точно. Например, потому, что в типе double нельзя точно выразить ни число 0.001, ни число 9.381. (иллюстрация, связанный ответ)
Вам нужно перейти к типу decimal, который специально для этого предназначен.
double x = 9.3813020199999;
decimal precision = 0.001m;
decimal result = Math.Round((decimal)x / precision) * precision; // 9.381
Если количество десятичных знаков известно в виде числа, можно проще:
double x = 9.3813020199999;
decimal result = Math.Round((decimal)x, 3); // 9.381
Обновление: Если оставаться в рамках типа double, вы не можете их сравнивать: равенство теоретически одинаковых чисел типа double, вычисленных разными путями — практически невероятное событие из-за ошибок округления. В таких случаях используется примерное равенство с точностью до epsilon. Например, в NUnit есть для таких целей специальные функции
Values of type float and double are normally compared using a tolerance specified by the Within modifier.
Комментариев нет:
Отправить комментарий