Toon posts:

[Delphi] programma geeft op sommige PC's afrondingsfout

Pagina: 1
Acties:

Verwijderd

Topicstarter
We hebben hier een vaag probleem:

We hebben +/- 20 Compaq EVO's D300 systemen waar de medewerkers mee werken, 1 van de programma's die gebruikt wordt is een door derden geschreven "klantenservice" programma waarin onder anderen facturen uitgedraaid kunnen worden. Alle programma's waaronder ook "Klantenservice" zijn gekoppeld aan een Microsoft SQL 2000 Enterprise in clusterconfiguratie.

Alle Compaq EVO's (op 2 na) lijken een afrondings probleem te hebben, een factuurbedrag komt uit op €36,59 i.p.v. €36,60. op overige systemen: Toshiba laptops en een vaagmerk laptop gaat het wel goed, factuur bedrag wordt netjes €36,60.

Alles systemen, compaq desktops en toshiba laptops zijn in principe software matig hetzelfde geconfigureerd:

Windows 2000 Professional
Servicepack 3
Laatste updates (windows update)
BDE (Borland Database Engine)
MDAC 2.7

Compaq EVO configuratie:
P4 1500Mhz / 1700Mhz
128Mb / 256Mb
20Gb


Ik zou haast gaan denken in een bug in het floatingpoint gedeelte van de P4's gebruikt in deze lijn EVO's of toch 1 of andere bug in het "Klantenservice" programma. Ik weet in ieder geval niet waar ik het zoeken moet en hoop dat 1 van jullie mij kan helpen.

[ Voor 8% gewijzigd door Verwijderd op 22-01-2003 11:04 ]


  • Brothar
  • Registratie: Oktober 2000
  • Laatst online: 04-02 09:14

Brothar

meester

broncode ?
De eerste vraag is, hoe dat bedrag van 36,59 wordt berekend. Als die geen reden geeft om te denken dat het een algoritme-fout is, dan kun je pas een een FP-cpu fout gaan denken.
Maar dan: dit had allang bekend moeten zijn - al op de site van Intel gekeken voor een melding, patch etc. ? - en Intel heeft dat wel met een PII gehad, dus het lijkt me niet aannemelijk dat ze het nu weer in een processor hebben ingebakken.

Ik heb vroeger hetzelfde probleem gehad bij een berekening in Pascal: kan een fout in de broncode zijn. Mail die eens.

[ Voor 13% gewijzigd door Brothar op 22-01-2003 11:14 ]

eagle


Verwijderd

Topicstarter
Ik heb de broncode niet, en denk ook niet dat ik die kan krijgen. Ik kan misscien de berekening van het factuur bedrag krijgen. (ga ik proberen)

Maar waarom gaat het voor de rest overal wel goed dan? Dan zou het toch haast geen programma probleem kunnen wezen. Lijkt mij tenminste...


edit:
effe gebeld, ik heb een stukje van de source gekregen, de volgende functie wordt gebruikt:
SimpleRoundTo(ACurrency*(ADouble/100)*Ord(ABoolean),-2)

ACurrency is een variabele van het type Curreny
ADouble is een variabele van het type Double
ABoolean is een variabele van het type Boolean

[ Voor 36% gewijzigd door Verwijderd op 22-01-2003 11:36 ]


  • Brothar
  • Registratie: Oktober 2000
  • Laatst online: 04-02 09:14

Brothar

meester

Is - althans dat was het bij mij dacht ik, ik heb nu over 1990 - een afronding bij meerdere cijfers achter de comma. Afronding kun je op een paar manieren programmeren. De 'fout' zit hem dan in de berekening even voor de berekening en afronding. Je moet in wezen elk tussenresultaat (eerder) afronden.
Je moet dus eigenlijk terug naar hoe het vroeger met de hand ging: welke bedragen/tussenresultaten rond je wel af op centen, en welke laat je tot x cijfers achter de comma staan.
Ter verduidelijking: als je 2 bedragen met elk 2 cijfers achter de comma met elkaar vermenigvuldigt, krijg je een bedrag van 4 cijfers achter de comma. De processor slaat dit binair op (ik kan me nog iets van een boekje assembler herinneren: BCD binairy coded decimal, dan gebeurde dit niet, maar dat programmeer je niet standaard in).
Het lijkt/leek erop dat bij afronding gewoon bitjes worden verwijderd. En ik weet nu niet meer precies hoe ik het destijds heb opgelost, ik dacht door gewoon eerder af te ronden, en aan te sluiten met hoe een boekhouder vroeger werkte.

Mail dan in ieder geval de berekening en bedragen eens.

[ Voor 4% gewijzigd door Brothar op 22-01-2003 11:34 ]

eagle


  • Brothar
  • Registratie: Oktober 2000
  • Laatst online: 04-02 09:14

Brothar

meester

SimpleRoundTo(ACurrency*(ADouble/100)*Ord(ABoolean),-2)

Ik moet even die functies opzoeken - probeer momenteel iets in Delphi te maken - is nieuw voor mij - heb gelukkig een trialversie gedownload die nog een paar dagen geldig is.
ZIE NU DAT HET VARIABELEN ZIJN.
SimpleRoundTo is dan zeker ook een zelf gebouwde functie ?


Zo op het eerste oog:
destijds de oude functie Round gebruikt, en dat was de boosdoener: heb ik destijds opgelost (dacht ik net al, maar ik was niet zeker, dus wilde je niet op een verkeerd spoor zetten) INT te gebruiken.
Voor afronding gebruik je dan (INT x+0,5)
en niet Round(x)
De boolean wordt blijkbaar gebruikt om te zien of het bedrag groter is dan een ander bedrag (kwantumkorting of BTW oid).
Mijn opmerking: gebruik gewoon een If .. Then ..
Is ook duidelijker.

Zoveel mogelijk code in 1 regel stoppen maakt het onleesbaar, terwijl het volgens mij niet sneller werkt.

[ Voor 17% gewijzigd door Brothar op 22-01-2003 11:54 ]

eagle


Verwijderd

Topicstarter
Klink wijs wat je alle schrijft! ;)
Ik hoop dat ze er wat mee kunnen, ik stuur het naar hun toe.
Als ik meer info krijg dan update ik het hier wel weer even.

thanx!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Ik heb even de titel gemod, zodat hij het probleem beter omschrijft

  • Brothar
  • Registratie: Oktober 2000
  • Laatst online: 04-02 09:14

Brothar

meester

Destijds werkte ik bij een Levensverzekeraar, en ik en de actuaris begrepen de foutieve afronding geen van 2-en. En een goede afronding van verzekeringspremies is toch wel relevant voor een verzekeraar.
De grap was dat het voorbij was toen we Int (x+0,5) gingen gebruiken. We begrepen het geen van beide. Ik kan me die vraag van de actuaris nog wel herinneren, en mijn reactie "ik weet het ook niet hoe het komt, maar wat maakt het uit, het werkt nu goed".
De mogelijk verklaring gaf ik hierboven: binaire opslag digitale cijfers x achter de comma.

Als je meer hoort, mail dan, mijn e-mail staat in mijn tweakers-account. Ik ben wel benieuwd naar de reactie. O, en als ze nog een programmeur zoeken ..
Ik zit alweer een tijdje thuis, vandaar die eigen Delphi-toepassing, misschien kan ik daar inkomen mee genereren.

[ Voor 21% gewijzigd door Brothar op 22-01-2003 12:18 ]

eagle


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
De code is fout. Bedragen moet je niet met floating-point mixen. Daarom heb je dus ook zo'n Currency type. Bedragen zijn nl. een geheel aantal centen. Alleen de I/O is bijzonder, daar moet je voor mensen een , invoegen op twee plaatsen voor het einde.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 22:35

Reptile209

- gers -

Misschien zit het 'm toch nog in het OS: de uitwerking van Currency wordt door de land/regioinstellingen gemaakt (juiste valutateken, aantal decimalen, punt of komma). Staan die op alle PC's precies gelijk (en draaien ze idd hetzelfde OS, zelfde SP)?

Zo heb ik hier eens gemerkt dat, bij het opzoeken van een dag van de week in Access, onder NT (engels) de week bij ondag begint, maar onder Win98SE (nederlands) de week op maandag begint...

Zo scherp als een voetbal!


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Reptile209 schreef op 22 January 2003 @ 12:51:
Misschien zit het 'm toch nog in het OS: de uitwerking van Currency wordt door de land/regioinstellingen gemaakt (juiste valutateken, aantal decimalen, punt of komma). Staan die op alle PC's precies gelijk (en draaien ze idd hetzelfde OS, zelfde SP)?
Dat is alleen de weergave. Intern veranderd de opslag van een datum of bedrag niet. Het Currency type is alleen voor Borland geldig. Het is een fixed point getal. Dat wil zeggen dat het een vast aantal getallen achter en voor de komma heeft. Het is intern dan ook een Int64. Hierdoor heb je minder kans op afrondingsfouten als bij floats. Currency rond af op 4 of 5 getallen achter de comma. Dat is volgens mij ook hoe de standaard is vastgesteld onder financiele instellingen.

We adore chaos because we like to restore order - M.C. Escher


  • Sardaukar
  • Registratie: Januari 2003
  • Laatst online: 16:58
Dit is een oud probleem waar ik vroeger ook eens tegen aangelopen ben.

Om het probleem van de afronding duidelijk te maken. Pak een willekeurige programmeertaal (of spreadsheet voor mijn part). Laat hierin de waarde 1 delen door 3. Laat het resultaat weer vermenigvuldigen met 3. Doe dan de volgende vergelijking: 1 = resultaat vermenigvuldiging met 3.

Deze vergelijking is dus false. Het resultaat is niet meer gelijk aan 1.

Daarom heb ik de volgende afrondingsroutine (tevens conversie naar
centen). VB-code (god helpe me)

Dim d As Double
Dim i As long
d = 4950,4950

i = Int((d * 100) + 0.5)

Overigens bestaan er voor Delphi zeer goede (open source) libraries waarin al standaard oplossingen voor afrondingen bestaan. Zoek op google maar eens naar 'Delphi JCL' en 'Delphi JVCL'

Toch vind ik het vreemd: de programmeurs veroorzaken die fout en jij (zonder toegang tot de code) moet maar met een oplossing komen? Rare zaak.

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

RoundTo doet dat ook in Delphi

We adore chaos because we like to restore order - M.C. Escher


  • Sardaukar
  • Registratie: Januari 2003
  • Laatst online: 16:58
Ach, bedankt.

Het lijkt me dat het probleem dan zit in de SimpleRoundTo functie. Er worden in die routine ook doubles gebruik terwijl het Currency-type me meer op zijn plaats lijkt. Maar goed, zonder volledige source-code blijft het gissen natuurlijk.

Verwijderd

Topicstarter
Sardaukar schreef op 22 January 2003 @ 14:57:
Dit is een oud probleem waar ik vroeger ook eens tegen aangelopen ben.

Om het probleem van de afronding duidelijk te maken. Pak een willekeurige programmeertaal (of spreadsheet voor mijn part). Laat hierin de waarde 1 delen door 3. Laat het resultaat weer vermenigvuldigen met 3. Doe dan de volgende vergelijking: 1 = resultaat vermenigvuldiging met 3.

Deze vergelijking is dus false. Het resultaat is niet meer gelijk aan 1.

Daarom heb ik de volgende afrondingsroutine (tevens conversie naar
centen). VB-code (god helpe me)

Dim d As Double
Dim i As long
d = 4950,4950

i = Int((d * 100) + 0.5)

Overigens bestaan er voor Delphi zeer goede (open source) libraries waarin al standaard oplossingen voor afrondingen bestaan. Zoek op google maar eens naar 'Delphi JCL' en 'Delphi JVCL'

Toch vind ik het vreemd: de programmeurs veroorzaken die fout en jij (zonder toegang tot de code) moet maar met een oplossing komen? Rare zaak.
hahaha... dat zou je normaal gesproken wel denken ja! :)
maar ik probeer gewoon vrijwillig een beetje mee te denken/zoeken om tot een oplossing te komen.
Pagina: 1