Страницы

Поиск по вопросам

суббота, 7 марта 2020 г.

C#. Как преобразовать число с плавающей точкой в аналогичное число, но только с заданным количеством знаков после запятой?

#c_sharp #net #double


Доброго времени суток! 

Возник следующий вопрос: к примеру, у нас есть переменная типа 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);
        }
    }

    


Ответы

Ответ 1



Если говорить о десятичных знаках, то оставаться в рамках типа 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.

Комментариев нет:

Отправить комментарий