C # Ошибка округления банкира
-
04-10-2019 - |
Вопрос
double a = 18.565
return Math.Round(a,2)
.. возвращает 18,57.
Для каждого другого номера я попробовал округление Banker работал, как ожидалось, например, Math. Round (2.565,2) вернулся 2,56.
Любое объявление, почему и когда это произойдет? Это ошибка или я что-то упускаю о округление банкира?
Спасибо..
Решение
Как сказал Мэтью, 18,565 не может быть точно представлена. Фактическая ценность используется 18.565000000000001278976924368180334568180334568023681640625 (Найдено с использованием DoubleConverter), который ясно, кроме наполовину. Теперь у меня есть ощущение, что иногда Math.Round
рассмотрит ценность, которое фактически за пределы половины точка, но что так близко к полупансию, как можно точно представить, как именно в этот момент. Однако я не видел никакой документации, описывающей ситуации, в которых применяется, и ясно, что в этом случае она не происходит. Я не хотел бы положиться на это.
Даже закругленное значение не ровно 18,57, конечно. На самом деле это 18,570000000000000002842170943040400743484497434844970703125.
Принципиально, если вы действительно, действительно заботитесь о представлять десятичные значения точно, вы должны использовать decimal
. Отказ Это не только с точки зрения Math.Round
- Он идет к каждому аспекту обработки значений с плавающей запятой.
Это делает дать правильное значение для Math.Round
, конечно:
decimal m = 18.565m;
Console.WriteLine(Math.Round(m, 2)); // Prints 18.56
Другие советы
18,565 не может быть точно представлено как двойной. Таким образом, двоичное представление немного выше, поэтому он раундут. Если вы используете десятичное:
decimal a = 18.565m;
return Math.Round(a,2)
Это может быть точно представлено, и у вас не будет этого вопроса.
Я предположил, что представление FP означает, что это на самом деле не является трейлинг 5; Опасности ФП!
Это работает нормально, хотя:
decimal a = 18.565M; // <===== decimal
var s = Math.Round(a, 2);
Двухместный - это значение с плавающей запятой, поэтому, может быть, если вы пишете его как 18,565, это на самом деле в памяти что-то вроде 18.56500000000000000000000000000000000000000000000000000000001, и, следовательно, это больше, чем средняя точка.