Странное поведение функции RoundTo на двух разных компьютерах

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

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

P.S 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`

so

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

они вошли

`c = 3675.05`

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


person Masoud    schedule 11.10.2011    source источник
comment
Мы бы тоже хотели увидеть этот странный код   -  person Awais Qarni    schedule 11.10.2011
comment
@Mitch Wheat Я разместил это. Это в PS и PS2.   -  person Masoud    schedule 11.10.2011
comment
Чтобы исследовать подобные вопросы, вам нужно научиться быть точным и научным. Невозможность опубликовать точный код, который вы используете, невозможность указать версию delphi — вот ваши фундаментальные проблемы. Вы должны научиться быть более точными.   -  person David Heffernan    schedule 11.10.2011
comment
Для вас, как разработчика программного обеспечения, важно понять, что нет ничего простого, как кажется, когда вы имеете дело с числами с плавающей запятой. Округлые или усеченные изображения, которые вы видите на экране, — лишь верхушка бинарного айсберга. прочитайте это: download.oracle.com/docs/cd /E19957-01/806-3568/   -  person Warren P    schedule 11.10.2011


Ответы (1)


Я бы сказал, что вы столкнулись с проблемой "банковского округления" и указали неверные данные :-) 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!! Возможно, то, что вы видите как 0,5, не совсем 0,5, а 0,49999999 или 0,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 :-) Ах... волшебный мир поплавков :-)

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

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

person xanatos    schedule 11.10.2011
comment
Было очень интересно и спасибо за информацию. Но моя проблема в другом. Я отредактирую свой вопрос для получения дополнительной информации. - person Masoud; 11.10.2011
comment
@Masoud Я только что написал выражение на C#: (Math.Round(7231.76, 1) - Math.Round(3556.71, 1)).ToString(r), и результат равен 3675.1000000000004 :-) - person xanatos; 11.10.2011
comment
@xanstos Я скомпилировал его и отправил исполняемый файл на другие компьютеры. У них нет версии делфи. и я ввел один и тот же номер в каждой программе. - person Masoud; 11.10.2011
comment
@Masoud И вы не указали, используете ли вы Single или Double - person xanatos; 11.10.2011
comment
Это числа с плавающей запятой. Я сам ввел 7231.76 и 3556.71 и 3675.05 в каждый компьютер. и все они используют один и тот же exe-файл. - person Masoud; 11.10.2011
comment
Как банковское округление может объяснить разные результаты на разных машинах? - person David Heffernan; 11.10.2011
comment
@DavidHeffernan Потому что в 5 случаях из 10 то, что ОП пишет в вопросе, не соответствует тому, что происходит на самом деле! Так что я экстраполировал это, и, в конце концов, этот класс проблем решается знанием Банковского округления или знанием того, что такое fp. Если вы погуглите Delphi RoundTo (или C# Math.Round), это проблемы, с которыми сталкиваются люди. - person xanatos; 11.10.2011
comment
Я не понял. Это не было решено. Но похоже ответа нет. и ответы xantos были лучшими. - person Masoud; 11.10.2011
comment
@Masoud Попробуйте объявить свои переменные как валюту, и это решит само собой. - person xanatos; 11.10.2011
comment
как сказал Давидхеффернан, это не объясняет разные результаты на разных машинах. Потому что все они запускают один и тот же exe-файл. - person Masoud; 11.10.2011
comment
Да. Это решено. Но я не могу понять, почему у меня были разные ответы на разных машинах. - person Masoud; 11.10.2011
comment
@masoud, безусловно, будет ответ, и мы могли бы помочь вам его найти. Для этого вам нужно будет дать полную программу, которая дает разные результаты на разных машинах. - person David Heffernan; 11.10.2011
comment
@Masoud Поскольку вы не указали версию используемого языка, вы не указали тип используемых вами переменных (и нет, с плавающей запятой недостаточно), в вашем первоначальном сообщении была эта строка. работа помоги мне. Люди здесь не читают мысли плакатов. - person xanatos; 11.10.2011
comment
@Masoud Добавлен пятый вариант ... Если то, что вы написали, действительно произошло, это объяснило бы это. - person xanatos; 11.10.2011
comment
Большое спасибо за вашу помощь. - person Masoud; 11.10.2011
comment
+1 за bankers rounding Я работаю дипломированным бухгалтером уже 10 лет, но могу сказать вам, что никто не использует это округление мозгов. Мы либо просто усекаем, потому что десятичные дроби несущественны, либо правильно округляем. - person Johan; 11.10.2011
comment
@johan, эту технику округления изучают в школе. Он дает правильное среднее значение для большого количества случайных округлений. - person LU RD; 11.10.2011
comment
@LU RD - не в моей школе не было. Нас учили 0,5 раунда UP. Никаких если и никаких но. - person Deltics; 11.10.2011