Согласно документации, decimal.Round
метод использует алгоритм округления до четности, который не является распространенным для большинства приложений. Поэтому я всегда заканчиваю тем, что пишу пользовательскую функцию для более естественного алгоритма округления до половины:
public static decimal RoundHalfUp(this decimal d, int decimals)
{
if (decimals < 0)
{
throw new ArgumentException("The decimals must be non-negative",
"decimals");
}
decimal multiplier = (decimal)Math.Pow(10, decimals);
decimal number = d * multiplier;
if (decimal.Truncate(number) < number)
{
number += 0.5m;
}
return decimal.Round(number) / multiplier;
}
Кто-нибудь знает причину этого решения дизайна структуры?
Есть ли встроенная реализация алгоритма округления до половины в рамках? Или, может быть, какой-то неуправляемый Windows API?
Это может ввести в заблуждение новичков, которые просто пишут, decimal.Round(2.5m, 0)
ожидая 3 в результате, но получая вместо этого 2.
Ответы:
Возможно, потому что это лучший алгоритм. В течение многих выполненных округлений вы в среднем получите, что все .5 округляются одинаково вверх и вниз. Это дает более точные оценки фактических результатов, если вы, например, добавляете несколько округленных чисел. Я бы сказал, что хотя это и не то, что некоторые могут ожидать, это, вероятно, более правильная вещь.
источник
Другие ответы с причинами, по которым алгоритм Банкира ( примерно половина к четному ) является хорошим выбором, вполне верны. Он не страдает от отрицательного или положительного смещения так же, как метод округления наполовину от нулевого метода по большинству разумных распределений.
Но вопрос был в том, почему .NET по умолчанию использует фактическое округление Banker - и ответ заключается в том, что Microsoft следовала стандарту IEEE 754 . Это также упоминается в MSDN для Math.Round под примечаниями.
Также обратите внимание, что .NET поддерживает альтернативный метод, указанный IEEE, предоставляя
MidpointRounding
перечисление. Конечно, они могли бы предоставить больше альтернатив для решения связей, но они решили просто выполнить стандарт IEEE.источник
Хотя я не могу ответить на вопрос «Почему дизайнеры Microsoft выбрали это по умолчанию?», Я просто хочу указать, что дополнительная функция не нужна.
Math.Round
позволяет указатьMidpointRounding
:источник
Десятичные знаки в основном используются для денег ; Банковское округление является обычным делом при работе с деньгами . Или вы могли бы сказать.
Преимущество округления банкиров заключается в том, что в среднем вы получите тот же результат, если вы:
Округление перед сложением сэкономило много работы за несколько дней до компьютеров.
(В Великобритании, когда мы пошли, десятичные банки не имели дела с половиной пенсов, но в течение многих лет все еще существовала монета в полпенса, и в магазинах часто цены заканчивались на полпенса - так много округлений)
источник
Decmial
с, да. Десятичных знаков нет Для потомков я согласен с первоначальным мнением здесь.Используйте другую перегрузку функции Round, например:
Это выведет 3 . И если вы используете
Вы получите банковское округление.
источник