[PHP] Afronding getallen m.b.v. round()

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Ik ben momenteel bezig met het ontwikkelen van een berekenings applicatie met behulp van PHP. Hierbij wordt er regelmatig gebruik gemaakt van het afronden van getallen. Nu kwam ik er achter dat bij sommige waardes er een verschil zit van 1 cent. Het blijkt te zitten in de afronding die niet helemaal goed verloopt.

Een quickfix is om de round 2x uit te voeren. Eerst af te ronden op 3 decimalen en daarna afronden op 2 decimalen. Ik maak gebruik van PHP5

Een voorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
<?php
$round1 = round(8.1246, 2);
echo $round1; // 8.12

// Quickfix
$round1 = round(8.1246, 3); //8.125
$round2 = round($round1, 2);
echo $round2; // 8.13
?>


Hoe kan het dat de round functie zo'n "fout" maakt? En is er een andere mogelijkheid voor het afronden van decimalen dat wel nauwkeurig is?

Acties:
  • 0 Henk 'm!

  • Chip.
  • Registratie: Mei 2006
  • Niet online
Euh? Die round functie werkt gewoon goed hoor... de afronding van 8.1246 op 2 decimalen is inderdaad 8.12 aangezien 4 nog altijd kleiner is dan 5...

kortom wanneer je wilt afronden op 2 decimalen wordt er altijd alleen gekeken naar 't 3de decimaal en niet naar de decimalen die erna komen...
en als je wilt afronden op 3 decimalen wordt er altijd alleen gekeken naar 't 4de decimaal enzovoort enzovoort...

Wikipedia: Afronden

[ Voor 25% gewijzigd door Chip. op 19-06-2009 15:35 ]


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Dat komt denk ik omdat je floating points gebruikt en daar een aantal operaties mee uitvoert. Dat is het probleem van het gebruiken van floats :)

Als je met alleen geld rekent, reken dan met integers die de centen voorstelt. Dan heb je het probleem niet meer.

/edit: nu lees ik je TS pas eigenlijk goed: 8.1246 hóórt ook af te ronden naar 8.12!

[ Voor 14% gewijzigd door mithras op 19-06-2009 15:34 ]


Acties:
  • 0 Henk 'm!

  • Peter
  • Registratie: Januari 2005
  • Laatst online: 31-05 21:41
(jarig!)
Ehm, dit is precies zoals het afronden werkt hoor. Gezien je zo te zien naar boven wilt afronden, zou je ook ceil kunnen gebruiken, al is dat iets minder net dan een enkele functie-call;

PHP:
1
printf ('%.2f', ceil (8.1246 * 100) / 100);


Verder zou je kunnen spelen met de round flags die sinds PHP 5.3 toegevoegd zijn (mocht je dat al kunnen gebruiken, anders komt de final volgende week uit), maar dan zou je nog steeds de berekening moeten gebruiken.

[ Voor 38% gewijzigd door Peter op 19-06-2009 15:36 ]


Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 01:43

Reptile209

- gers -

Het hangt een beetje van je definitie van afronden af of dit fout is. Het is niet ongebruikelijk (sterker nog: in mijn optiek is het de enige juiste manier) om bij afrondingen alleen naar de laatste decimaal die komt te vervallen te kijken. Dan levert de afronding van 1,44444444446 op hele getallen netjes 1 op (komt neer op het afronden van 1,4) en niet 2 (afronden van 1,5).
De enige juiste aanpak is om altijd te rekenen met de oorspronkelijke waarden, zonder afronden tussendoor (het afronden dat je systeem doet omdat sommige getallen niet in bits te vangen zijn daargelaten). Pas bij je eindantwoord ga je afronden. En als je dan persé wil dat ook de verdere decimalen meetellen, kan je via een lusje de n decimalen die je mee wil nemen één voor één afronden, analoog aan je voorbeeld. Moet je dus wel even bedenken hoe ver je daarin wil gaan...

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Conclusie uit bovenstaande reacties: de afronding gaat niet fout waar 8.1246 als 8.12 wordt weergegeven, maar juist waar 8.1246 als 8.13 wordt weergegeven. Je zoekt net op de verkeerde plaats, want je code is goed.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Bedankt voor jullie reacties. Het is mij het een en ander duidelijk geworden. Ik maak nu gebruik van mijn"quickfix". Deze lost in principe 99,9849 % van het probleem op :)

Acties:
  • 0 Henk 'm!

Anoniem: 156876

Ik weet niet waarom je dit wilt "quickfixen" want eigenlijk fix je er niks aan, het hoort niet zo afgerond te worden.

Maar misschien heb je hier wat aan:
PHP:
1
2
3
4
5
6
<?php
function ceiling($value, $precision = 0)
{
    return ceil($value * pow(10, $precision)) / pow(10, $precision);
}
?>
bron: http://nl.php.net/ceil

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Heel simpel gezegd, die quickfix die sloopt het eerder dan dat hij het fixed.

Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Gomez12 schreef op vrijdag 19 juni 2009 @ 16:16:
Heel simpel gezegd, die quickfix die sloopt het eerder dan dat hij het fixed.
Slopen of niet, voor mij is de uitkomst daarmee correct. Het mag dan wel geen "fix" zijn omdat de afronding volgens de functie juist is, in mijn optiek is het een fix om zodoende een afronding te creëren die voor mij juist is.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
DeepFreeze.NL schreef op vrijdag 19 juni 2009 @ 16:20:
[...]

Slopen of niet, voor mij is de uitkomst daarmee correct. Het mag dan wel geen "fix" zijn omdat de afronding volgens de functie juist is, in mijn optiek is het een fix om zodoende een afronding te creëren die voor mij juist is.
Kan je dan eens uitleggen waarom het voor jou juist is? Ik kan me geen situatie bedenken waarin jouw manier van afronden logischer is dan de normale!

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Canaria
  • Registratie: Oktober 2001
  • Niet online

Canaria

4313-3581-4704

Een betere quickfix is om wel gebruik te maken van de round-functie, maar het getal vooraf met jouw correctie (0,0005) te verhogen.
Dus
PHP:
1
2
$round1 = round((getal + 0.0005), 2); 
echo $round1;

Apparticle SharePoint | Apps | Articles


Acties:
  • 0 Henk 'm!

  • DeepFreeze.NL
  • Registratie: April 2006
  • Laatst online: 02-03 08:01
Woy schreef op vrijdag 19 juni 2009 @ 16:27:
[...]

Kan je dan eens uitleggen waarom het voor jou juist is? Ik kan me geen situatie bedenken waarin jouw manier van afronden logischer is dan de normale!
Ik ben een berekening aan het ontwikkelen welke gelijk moet zijn met de berekening uit een Excel bestand. De uitkomst van de berekening in PHP is met behulp van "mijn" afronding wel gelijk aan de berekening in Excel. Als ik gebruik maak van de standaard round($getal,2) afronding dan krijg ik dus een verschil van enkele centen.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik zie niet in waarom je 1,1246 naar 1,13 zou willen afronden? Ga je 1,12446 dan ook naar 1,13 afronden? En waar ligt de grens dan?

Het is toch gewoon logisch om naar het dichtsbijzijnde getal met het gewenst aantal decimalen af te ronden?
DeepFreeze.NL schreef op vrijdag 19 juni 2009 @ 16:35:
[...]
Ik ben een berekening aan het ontwikkelen welke gelijk moet zijn met de berekening uit een Excel bestand. De uitkomst van de berekening in PHP is met behulp van "mijn" afronding wel gelijk aan de berekening in Excel. Als ik gebruik maak van de standaard round($getal,2) afronding dan krijg ik dus een verschil van enkele centen.
Dan zit er dus een fout in de round functie van Excel, en kun je imho beter daar naar kijken

[ Voor 53% gewijzigd door Woy op 19-06-2009 16:38 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Anoniem: 112308

Dat verschil zal niet zomaar onstaan, ik zou even naar de precieze oorzaak daarvan zoeken. Wellicht tussentijds afronden dat het verschil maakt?

Acties:
  • 0 Henk 'm!

Anoniem: 156876

DeepFreeze.NL schreef op vrijdag 19 juni 2009 @ 16:35:
[...]

Ik ben een berekening aan het ontwikkelen welke gelijk moet zijn met de berekening uit een Excel bestand. De uitkomst van de berekening in PHP is met behulp van "mijn" afronding wel gelijk aan de berekening in Excel. Als ik gebruik maak van de standaard round($getal,2) afronding dan krijg ik dus een verschil van enkele centen.
Als het gelijk moet zijn uit die excel, waarom moet je het dan nog berekenen? Dan kan je net zo goed gelijk de waarde uit Excel pakken? :P

Acties:
  • 0 Henk 'm!

  • Cousin Boneless
  • Registratie: Juni 2008
  • Laatst online: 28-02 12:55
Klinkt als "bankers' rounding".. maar dat is toch nog iets subtieler dan 2x afronden.
Leuk om aan je leraar voor te stellen: of 'ie van je 5.4 een 5.5 wil maken zodat het een 6 wordt :)

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik heb het even in excel getest, maar die rond 1,1246 gewoon af naar 1,12 met round( 1,1246, 2 )

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Als je het gedrag in die Excel sheet niet begrijpt, is het inderdaad een strak plan om in PHP een compleet arbitraire pleister toe te voegen.

{signature}


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Cousin Boneless schreef op vrijdag 19 juni 2009 @ 16:39:
Klinkt als "bankers' rounding".. maar dat is toch nog iets subtieler dan 2x afronden.
Leuk om aan je leraar voor te stellen: of 'ie van je 5.4 een 5.5 wil maken zodat het een 6 wordt :)
Ik heb het even opgezocht, maar "bankers' rounding" is volgens wikipedia gewoon de round-to-even method. Dat heeft dus alleen invloed als je een 5 moet afronden, die normaal meestal omhoog afgerond word, maar bij round-to-even naar het dichtsbijzijnste even getal.

Dus:
2,5 = 2
en
3,5 = 4

[ Voor 7% gewijzigd door Woy op 19-06-2009 16:46 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • winkbrace
  • Registratie: Augustus 2008
  • Laatst online: 08-06 16:00
Toch ken ik ook wel systemen waarbij zo'n afronding ingeprogrammeerd is om de nodige extra centjes los te pulken..

In het geval van de TS is er ongetwijfeld een fout in de excel. Maar misschien is dat dus wel een opzettelijke.

Acties:
  • 0 Henk 'm!

Anoniem: 112308

BazzPsychoNut schreef op vrijdag 19 juni 2009 @ 17:14:
Toch ken ik ook wel systemen waarbij zo'n afronding ingeprogrammeerd is om de nodige extra centjes los te pulken..

In het geval van de TS is er ongetwijfeld een fout in de excel. Maar misschien is dat dus wel een opzettelijke.
Nou ja 'fout', in ieder geval een verschil met de php berekening. Maar die moeten gewoon gelijk te trekken zijn, lijkt me stug dat Excel ergens anders afrondt/rekent dan php.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 01-06 18:50

NMe

Quia Ego Sic Dico.

BazzPsychoNut schreef op vrijdag 19 juni 2009 @ 17:14:
Toch ken ik ook wel systemen waarbij zo'n afronding ingeprogrammeerd is om de nodige extra centjes los te pulken..
Maar dan gebruik je in dat geval toch juist ceil in plaats van round? :?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

DeepFreeze.NL schreef op vrijdag 19 juni 2009 @ 16:35:
[...]
Ik ben een berekening aan het ontwikkelen welke gelijk moet zijn met de berekening uit een Excel bestand.
Ik denk dat je de auteur van het Excel bestand er op moet wijzen dat zijn Excel bestand niet-standaard afrond. Mogelijk komt dat doordat hij tussendoor afrond en hij dus gewoon echt fout zit. Vraag op z'n minst of het echt de bedoeling is: er is geen enkele reden om aan te nemen dat het Excel sheet juist is, al is het door de hoofdaccountant van een mega-concern samengesteld.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Icekiller2k6
  • Registratie: Februari 2005
  • Nu online
tja wat hij wilt feitelijk is dit:
als je dit getal hebt
1,45789
dan pakt hij afronding tot 4
zodat je:
1,4579 uitkomt, dan afronding tot 3
zodat je 1,458 uitkomt.. en dan afronding tot 2,
1,46

Als je nu dit getal pakt
1,43289
dan zou het
1,43 zijn.

MT Venus E 5KW (V151) P1 HomeWizard | Hackerspace Brixel te Hasselt (BE) - http://www.brixel.be


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Pfff, je moet wel heel goed spul roken voordat je daar de ideale logica in ziet. 8)7

Als je de helft van de keren naar beneden afronden niet eerlijk vind, kies je maar voor ceil(). Of je bouwt zelf bovenstaand algo (max 2 minuten werk), maar verwacht dan niet dat iedereen je manier van afronden begrijpt.

{signature}


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Icekiller2k6 schreef op vrijdag 19 juni 2009 @ 18:51:
tja wat hij wilt feitelijk is dit:
als je dit getal hebt
1,45789
dan pakt hij afronding tot 4
zodat je:
1,4579 uitkomt, dan afronding tot 3
zodat je 1,458 uitkomt.. en dan afronding tot 2,
1,46

Als je nu dit getal pakt
1,43289
dan zou het
1,43 zijn.
Maar leg me dan eens uit wanneer dat een logische manier van afronden zou zijn?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Icekiller2k6
  • Registratie: Februari 2005
  • Nu online
Woy schreef op zaterdag 20 juni 2009 @ 10:23:
[...]

Maar leg me dan eens uit wanneer dat een logische manier van afronden zou zijn?
heb nooit gezegd dat dat een logische manier is. Ik zeg gewoon hoe hij het wilt..

hij wilt feitelijk een functie die kijkt hoeveel komma getallen er zijn. En dan afronding tot -1 dervan.
dus als je 5 komma getallen hebt, dan rond je af tot 4.. als je dat gedaan hebt dan rond je dat getal af tot 3 getallen na de komma.. en dan tot 2.

Als je dat zo doet krijg je verschillende uitkomsten vb:
1,7449
als je dat rond op 2 na de komma dan heb je 1,74

als je doet hoe ik het zeg.. dan heb je 1,75

(1,7449 => 1,745 => 1,75)

edit:
het feit is dat de belastingen de onderstaande manier gebruikt.. Hoe weet ik dit? Mijn pa werkt bij de belastingen... En het is gekend dat sommige mensen rekenfouten maken.. het beste wat je kunt doen voor BTW te berekenen op een factuur is
totaal bedrag nemen en daar BTW op berekenen.. want als je het 'stuk voor stuk' berekend en dan optelt heb je afrondingsfouten.. en dat kan op facturen, met veel goederen met komma getallen, tot problemen zorgen..


als je de bovenstaande situatie hebt zoals ik het zei en 100 producten hebt zo.. dan heb je 100x 0,01 verkeerd.. dat is 1 euro.. en ja daar valt de belastingen over ;), vooral omdat je dan op een verkeerd getal uw BTW berekend... zodat je een 'dubbele' fout krijgt..

[ Voor 33% gewijzigd door Icekiller2k6 op 20-06-2009 11:31 ]

MT Venus E 5KW (V151) P1 HomeWizard | Hackerspace Brixel te Hasselt (BE) - http://www.brixel.be


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Icekiller2k6 schreef op zaterdag 20 juni 2009 @ 11:25:
het feit is dat de belastingen de onderstaande manier gebruikt..
[..]
het beste wat je kunt doen voor BTW te berekenen op een factuur is totaal bedrag nemen en daar BTW op berekenen..
Ja natuurlijk, maar dat heeft niets te maken met de manier van afronden. Dat heeft te maken met de momenten waarop je afrond. Je berekent belasting over het onafgeronde totaalbedrag, waarbij 1.4449 aan belasting nog steeds 1.44 wordt. Daarna tel je dat bedrag bij het BTW-loze totaalbedrag op en rond op de normale manier af. Dan zit die ene cent voor belastingen er altijd in als dat nodig is.

Voorbeeld:
Als in de supermarkt iets als 2.02 EUR geprijsd is, dan kost het 2.02 / 1.19 = 1.69748 zonder belasting en de belasting is 0.32252. Als dat het enige product is dat je koopt, dan krijgt de winkel 1.70 EUR en de belastingdienst 0.32. Niets aan de hand. Koop je echter 2 van die producten, dan krijgt de winkel 3.3949 =3.39 en de belastingdienst 0.645 = 0.65. De afronding gaat over het totaal, niet per deelbedrag.

[ Voor 31% gewijzigd door Confusion op 20-06-2009 11:45 ]

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Icekiller2k6 schreef op zaterdag 20 juni 2009 @ 11:25:
[...]


heb nooit gezegd dat dat een logische manier is. Ik zeg gewoon hoe hij het wilt..

hij wilt feitelijk een functie die kijkt hoeveel komma getallen er zijn. En dan afronding tot -1 dervan.
dus als je 5 komma getallen hebt, dan rond je af tot 4.. als je dat gedaan hebt dan rond je dat getal af tot 3 getallen na de komma.. en dan tot 2.

Als je dat zo doet krijg je verschillende uitkomsten vb:
1,7449
als je dat rond op 2 na de komma dan heb je 1,74

als je doet hoe ik het zeg.. dan heb je 1,75

(1,7449 => 1,745 => 1,75)

edit:
het feit is dat de belastingen de onderstaande manier gebruikt.. Hoe weet ik dit? Mijn pa werkt bij de belastingen... En het is gekend dat sommige mensen rekenfouten maken.. het beste wat je kunt doen voor BTW te berekenen op een factuur is
totaal bedrag nemen en daar BTW op berekenen.. want als je het 'stuk voor stuk' berekend en dan optelt heb je afrondingsfouten.. en dat kan op facturen, met veel goederen met komma getallen, tot problemen zorgen..


als je de bovenstaande situatie hebt zoals ik het zei en 100 producten hebt zo.. dan heb je 100x 0,01 verkeerd.. dat is 1 euro.. en ja daar valt de belastingen over ;), vooral omdat je dan op een verkeerd getal uw BTW berekend... zodat je een 'dubbele' fout krijgt..
Zoals confiusion het ook al zegt is het dus niet zo dat de belastingdienst afrond op de manier dat jij zegt. Het is alleen zo dat het soms per item lijkt alsof dat zo is, maar dat komt omdat het over het totaal bedrag berekend word.

Verder lees ik ook niet direct dat dat de manier is dat hij het wil, hij wil dezelfde uitkomst krijgen als de Excel sheet. Blijkbaar gebeurt daar iets vreemds in, en dus zul je eerst moeten onderzoeken wat de excel sheet precies doet. Want Excel rond zelf ook op de goede manier af, er is dus meer aan de hand bij het excel sheet.

[ Voor 9% gewijzigd door Woy op 20-06-2009 12:46 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1