Странно поведение на функцията RoundTo в два различни компютъра

Проблемът е прост и странен! Написах програма в Delphi и използвах функция roundto. В един компютър 1,5 е закръглено до 2, а в друг компютър е закръглено до 1. Как може да се случи това?

P.S: Код------> 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!! Може би това, което виждате като .5, не е точно .5, а е .49999999 или .500000001. Ако искате да го проверите, влезте в програмата за отстраняване на грешки и проверете дали c = 3675.05 (логическият израз) е вярно или невярно, дали round(c, -1) = 3675.1 е вярно или невярно и т.н. Ако искате да изследвате света на fp, опитайте това: http://pages.cs.wisc.edu/~rkennedy/exact-float

Четвърта възможност: закръгляването на 3675,05 се променя, ако използвате Единично или Двойно. При единична е 3675.1, при двойна е 3675 :-) Ах... вълшебният свят на плувките :-)

Когато искате да правите математически трикове, моля, използвайте типа валута (това е число с фиксирана точка и няма тези проблеми).

Има последна възможност, но тя е доста невероятна: процесорът на Intel съхранява междинните резултати от операциите Double като 80 бита fp и след това ги "закръгля" до 64 бита при извеждане. Някои компилатори/езици въвеждат незадължителна оптимизация (която се активира при изпълнение на програмата, ако е възможно), за да се използват кодовете за операции SSE2, налични в някои процесори, вместо FPU на процесора. SSE2 работи на 64 бита fp, така че няма възходящо предаване до 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 Компилирах го и изпратих exe файла на други компютри. Те нямат версия на delphi. и във всяка програма въведох същия номер. - person Masoud; 11.10.2011
comment
@Masoud И не сте посочили дали използвате единичен или двоен - 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 това, което OP пише във въпроса, не е това, което наистина се случва! Така че аз го екстраполирах и в крайна сметка този клас проблеми се разрешават чрез познаване на Банковото закръгляване или познаване на това какво е fp. Ако търсите в Google за 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
както каза davidheffernan, това не обяснява различни резултати на различна машина. Защото всички изпълняват един и същи 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 кръга НАГОРЕ. Без ако и без но. - person Deltics; 11.10.2011