Подтвердить что ты не робот

Странное "полу-четное" округление на разных языках

GNU bash, версия 4.2.24:

$> printf "%.0f, %.0f\n" 48.5 49.5
48, 50

Ruby 1.8.7

> printf( "%.0f, %.0f\n", 48.5, 49.5 )
48, 50

Perl 5.12.4

$> perl -e 'printf( "%.0f, %.0f\n", 48.5, 49.5 )'
48, 50

gcc 4.5.3:

> printf( "%.0f, %.0f\n", 48.5, 49.5 );
48, 50

GHC, версия 7.0.4:

> printf "%.0f, %.0f\n" 48.5 49.5
49, 50

В Википедии говорится, что этот вид округления называется от половины до четного:

Это режим округления по умолчанию, используемый в вычислительных функциях и операторах IEEE 754.

Почему это округление используется по умолчанию в C, Perl, Ruby и bash, но не в Haskell?

Это какая-то традиция или стандарт? И если это стандарт, почему он используется этими языками и не используется Haskell? Какая точка округления до половины?

4b9b3361

Ответ 1

GHCi> round 48.5
48
GHCi> round 49.5
50

Единственное различие заключается в том, что printf не использует round - предположительно потому, что он должен иметь возможность округлять больше, чем целые целые числа. Я не думаю, что IEEE 754 указывает на то, как реализовать printf -форматные функции форматирования, просто округляя, что Haskell делает правильно.

Было бы лучше, если бы printf соответствовал реализациям round и других языков, но я не думаю, что это действительно очень важно.

Ответ 2

"Раунд до четности" используется по умолчанию для IEEE 754. Возможно, Haskell переключится на использование его в printf по причинам согласованности. Соответствующая строка кода находится в GHC.Float

f 0 (x:_)  = (if x >= b2 then 1 else 0, [])

Итак, если кто-то хочет это исправить, они могут это сделать. Как ни странно, это просто сделает функцию roundTo используемой printf совместимой с round, хотя я не уверен, что другой код изменит это изменение.

РЕДАКТИРОВАТЬ: предыдущая версия этого ответа неправильно определила местоположение кода округления. Единственное существенное различие между двумя реализациями заключается в том, что они жестко закодированы для использования базы 10.

Ответ 3

Я не могу сказать точно, но это, вероятно, связано с тем фактом, что этот тип округления обычно используется в бухгалтерских функциях, так как это также называется округлением Banker. Если вы посмотрите дальше в статье Википедии об округлении, вы также заметите, что это значение по умолчанию в IEEE 754, поэтому Haskell не соответствует этому стандарту.