Странное поведение функции RoundTo на двух разных компьютерах - PullRequest
3 голосов
/ 11 октября 2011

Проблема проста и странна!Я написал программу на Delphi и использовал функцию roundto.На одном компьютере 1,5 округляется до 2, а на другом - до 1. Как это могло произойти?

PS: Код ------> Roundto (1.5, 0)

PS 2: Кажется, нужно больше информации, поэтому я публикую более точные детали.Я написал программу.Они ввели два числа: a = 7231.76 b = 3556.71 Теперь они могут ввести третье число c, если c> = a - b, но точное образование в моем коде равно

`roundto(c, -1) >= roundto(a, -1) - roundto(b, -1)`
`roundto(a, -1) = 7231.8`
`roundto(b, -1) = 3556.7`

, поэтому

`roundto(a, -1) - roundto(b, -1) = 3675.1`

они вошли

`c = 3675.05`

Я проследил программу.На одном компьютере написано round(c, -1) = 3675.1, на другом - round(c, -1) = 3675.0

1 Ответ

9 голосов
/ 11 октября 2011

Я бы сказал, что вы столкнулись с проблемой «округления банковского счета» и отправили неверные данные :-) Delphi RoundTo реализует округление банковского счета: нечетные числа, заканчивающиеся на .5, округляются в большую сторону, это традиционное поведение, но ..Четные числа, оканчивающиеся на .5, округляются вниз!Таким образом, 1,5 округляется до 2,0, а 2,5 округляется до 2,0 (ссылка на ссылку RoundTo )

Вторая возможность: http://www.merlyn.demon.co.uk/pas-chop.htm#DRT В некоторых версиях есть ошибкаDelphi.У вас одна и та же версия Delphi на всех машинах?

Третья возможность: вы говорите о числах с плавающей запятой!Они не являются точными числами!Сложение и вычитание их создает микромир десятичных знаков, обычно невидимых 0.1 + 0.2! = 0.3 !!Возможно, что вы видите как .5 не совсем .5, но .49999999 или .500000001.Если вы хотите проверить это, войдите в отладчик и проверьте, является ли c = 3675.05 (логическое выражение) истинным или ложным, если round(c, -1) = 3675.1 истинным или ложным, и так далее.Если вы хотите исследовать мир fp, попробуйте следующее: http://pages.cs.wisc.edu/~rkennedy/exact-float

Четвертая возможность: округление 3675.05 изменяется, если вы используете Single или Double.Для Single это 3675,1, для Double - 3675 :-) Ах ... волшебный мир поплавков: -)

Если вы хотите делать математические трюки, используйте тип Currency (это число с фиксированной точкой)и не имеет этих проблем).

Существует последняя возможность, но она совершенно невероятна: процессор Intel сохраняет промежуточные результаты операций Double как 80 бит fp, а затем "округляет" их до 64 бит на выходе,Некоторые компиляторы / языки вводят дополнительную оптимизацию (которая активируется при запуске программы, если это возможно), чтобы использовать коды операций SSE2, присутствующие в некоторых процессорах, вместо FPU процессора.SSE2 работает на 64-битной частоте кадров, поэтому не нужно повышать до 80 бит и понижать с 80 бит.Это может привести к тому, что вы видите.Прочитайте здесь Различия между x87 FPU и SSE2 .

...