[PHP] Afronding klopt niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • kaandorp
  • Registratie: November 1999
  • Laatst online: 19-09 22:48
Ik ben een shopping cart aan het maken, maar loop tegen een vreemd probleem aan.
In de shoppingcart class heb ik een functie GetCartTotal(). Deze geeft het totaalbedrag weer. De functie ziet er als volgt uit:
PHP:
1
2
3
4
5
function GetCartTotal() {
    $carttotal = ($this->GetItemTotal() * 1.19);
    $carttotal = round($carttotal, 2);
    return $carttotal;
}


Laten we er vanuit gaan dat GetItemTotal de waarde 255.5 teruggeeft. Dit is een floatwaarde. Dat heb ik getest.
Als ik regel 3 uitcomment is de output van de functie 304.045. Zet ik echter 3 weer aan, dan wordt de output 304.04 :?
Maar als ik gewoon intik: echo round(304.045, 2); dan krijg ik 304.05 (wat klopt).

Iemand enig idee waarom er bij het ene .04 uitkomt en bij het andere .05?

Hieronder nog een screenshot van de cart. Bovenin heb ik een var_dump van de waarde gedaan die ik onderin met de functie GetCartTotal afrond. Zoals je ziet staat er 304,04, wat 304,05 zou moeten zijn.
Afbeeldingslocatie: http://www.nedrad.nl/other/afronding.png

Acties:
  • 0 Henk 'm!

  • phYzar
  • Registratie: November 2001
  • Laatst online: 22:33
de reden is geloof ik dat wanneer je veel waardes afrond en het gemiddelde neemt, dat het dan echt gemiddeld is, ipv net iets hoger omdat alles naar boven is afgerond.

de users op php.net raden zoiets aan:

PHP:
1
2
3
4
5
6
<?php
   $actual_value = 3.45;              // 3.45
   $temp1 = $actual_value * 2;        // 6.9
   $temp2 = round($temp1, 0);  // 7
   $half_round = $temp2 / 2            // 3.5
?> 

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Je kunt ook number_format gebruiken, heb je ook meteen de juiste notatie.
<?echo "€" . number_format(304.045, 2, ",", ".");?>
Geeft als het goed is; €304,05

[ Voor 17% gewijzigd door frickY op 24-09-2004 19:27 ]


Acties:
  • 0 Henk 'm!

  • kaandorp
  • Registratie: November 1999
  • Laatst online: 19-09 22:48
frickY schreef op 24 september 2004 @ 19:26:
Je kunt ook number_format gebruiken, heb je ook meteen de juiste notatie.
<?echo "€" . number_format(304.045, 2, ",", ".");?>
Geeft als het goed is; €304,05
Nope. Ook die geeft 304,04. Dat is het rare.

[ Voor 85% gewijzigd door kaandorp op 24-09-2004 19:32 ]


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Standaard fout. De output is geen 304.045 zijn, maar 304.04499... oid. Dat is omdat je geen intern niet werkt met decimalen achter de komma, maar met bits achter de komma. De mogelijke waarden zijn 1/2, 1/4, 1/8, etcetera. Daarmee kun je niet 45/1000 maken. Intern wordt er dus al afgerond op 0.00001011 nogwat. Dat ligt dichter bij 304.04 dan 304.05, en dus is dat het resultaat van afronden.

Je echte fout is dat je een (euro) bedrag niet als een geheel bedrag behandelt. Ik geloof dat je formeel in micro-euro's moet rekenen, maar in de praktijk kom je weg als je gewoon overal in centen rekent. Het gevolg is dat je resultaat dan 25550*1.19 = 30404,5 is. Dat is dus wel precies.

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


Acties:
  • 0 Henk 'm!

  • kaandorp
  • Registratie: November 1999
  • Laatst online: 19-09 22:48
MSalters schreef op 24 september 2004 @ 19:43:
Standaard fout. De output is geen 304.045 zijn, maar 304.04499... oid. Dat is omdat je geen intern niet werkt met decimalen achter de komma, maar met bits achter de komma. De mogelijke waarden zijn 1/2, 1/4, 1/8, etcetera. Daarmee kun je niet 45/1000 maken. Intern wordt er dus al afgerond op 0.00001011 nogwat. Dat ligt dichter bij 304.04 dan 304.05, en dus is dat het resultaat van afronden.

Je echte fout is dat je een (euro) bedrag niet als een geheel bedrag behandelt. Ik geloof dat je formeel in micro-euro's moet rekenen, maar in de praktijk kom je weg als je gewoon overal in centen rekent. Het gevolg is dat je resultaat dan 25550*1.19 = 30404,5 is. Dat is dus wel precies.
Dus ik zou in theorie kunnen doen:
vermenigvuldigen met 100
vermenigvuldigen met 1.19
afronden op 0 decimalen
delen door 100

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Tel standaard altijd 0.005 bij je totaal op, en doe daar dan de round/number_format van. Dan krijg je als het goed is wel altijd wat goeds uit. :)

'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.

Pagina: 1