Hallo,

Ik kom een probleem tegen bij het verwerken van mutaties. Dit probleem heb ik teruggebracht tot onderstaand script, hetgeen de output levert zoals onder is weergegeven (behalve de kleur dan).
Regel 3*3,29 en 6*3,29 worden weergegeven met ONGELIJK, maar volgens mij zouden deze ook gelijk moeten zijn.
Een prijs wordt vermenigvuldigd met het aantal en gecontroleerd met het opgegeven bedrag.
Er zit een conversie in (komma naar punt).
Een andere prijs opvoeren in $a (bv 1,11) geeft weer andere regels als verschil; $a = "1,23" geeft alles goed.
Al dagen aan het zoeken!
Wat doe ik fout?


<?php
echo 'Current PHP version: ' . phpversion();
$a = "1,12";
$b = array();
for ($aantal=1;$aantal<10;$aantal++)
{
$prijs = trim(str_replace(",", ".", $a));
$bedrag = $aantal*trim(str_replace(",", ".", $a));
$b[$aantal] = $aantal*$prijs;
$kleur = "black";
$fout = "";
$controlebedrag = trim(str_replace(",", ".", $b[$aantal]));
if ($bedrag <> $controlebedrag):
$fout = "ONGELIJK!!!";
$kleur = "red";
endif;
echo "<font color = $kleur><br>".$aantal."*".$a."=".$bedrag." ".$b[$aantal]." ".$controlebedrag."</font> ".$fout;
}?>
Geeft als output:

Current PHP version: 5.4.16
1*3,29=3.29 3.29 3.29
2*3,29=6.58 6.58 6.58
3*3,29=9.87 9.87 9.87 ONGELIJK!!!
4*3,29=13.16 13.16 13.16
5*3,29=16.45 16.45 16.45
6*3,29=19.74 19.74 19.74 ONGELIJK!!!
7*3,29=23.03 23.03 23.03
8*3,29=26.32 26.32 26.32
9*3,29=29.61 29.61 29.61
Waarom $a = "3,29"; en niet gewoon direct het juiste getal $a = 3.29; ?
De waarde van $a wordt extern aangeleverd!

[size=xsmall]Toevoeging op 25/06/2015 16:04:01:[/size]

Karel Bijvelds op 25/06/2015 15:45:26

Hallo,

Ik kom een probleem tegen bij het verwerken van mutaties. Dit probleem heb ik teruggebracht tot onderstaand script, hetgeen de output levert zoals onder is weergegeven (behalve de kleur dan).
Regel 3*3,29 en 6*3,29 worden weergegeven met ONGELIJK, maar volgens mij zouden deze ook gelijk moeten zijn.
Een prijs wordt vermenigvuldigd met het aantal en gecontroleerd met het opgegeven bedrag.
Er zit een conversie in (komma naar punt).
Een andere prijs opvoeren in $a (bv 1,11) geeft weer andere regels als verschil; $a = "1,23" geeft alles goed.
Al dagen aan het zoeken!
Wat doe ik fout?


<?php
echo 'Current PHP version: ' . phpversion();
$a = "3,29";
$b = array();
for ($aantal=1;$aantal<10;$aantal++)
{
$prijs = trim(str_replace(",", ".", $a));
$bedrag = $aantal*trim(str_replace(",", ".", $a));
$b[$aantal] = $aantal*$prijs;
$kleur = "black";
$fout = "";
$controlebedrag = trim(str_replace(",", ".", $b[$aantal]));
if ($bedrag <> $controlebedrag):
$fout = "ONGELIJK!!!";
$kleur = "red";
endif;
echo "<font color = $kleur><br>".$aantal."*".$a."=".$bedrag." ".$b[$aantal]." ".$controlebedrag."</font> ".$fout;
}?>
Geeft als output:

Current PHP version: 5.4.16
1*3,29=3.29 3.29 3.29
2*3,29=6.58 6.58 6.58
3*3,29=9.87 9.87 9.87 ONGELIJK!!!
4*3,29=13.16 13.16 13.16
5*3,29=16.45 16.45 16.45
6*3,29=19.74 19.74 19.74 ONGELIJK!!!
7*3,29=23.03 23.03 23.03
8*3,29=26.32 26.32 26.32
9*3,29=29.61 29.61 29.61


<?php
echo 'Current PHP version: ' . phpversion();
$a = "1,12";
$prijs = strval(str_replace(",", ".", $a));
for ($aantal=1;$aantal<10;$aantal++)
{
echo "<br>".$aantal."*".$a."=".($aantal*$prijs);
}
?>
Dank voor de reactie!

De verwijzing van Ward van der Put gevolgd en bekeken.

Als oplossing kies ik voor het standaardiseren van de uitkomsten en deze dan te vergelijken.
Zo loopt iig mijn script.
Indien iemand een elegantere oplossing heeft dan verneem ik dat graag.

<?php
echo 'Current PHP version: ' . phpversion();
$a = "3,29";
$b = "9,87";
$aantal = 3;
$prijs = number_format(str_replace(",", ".", $a),2);
$bedrag = number_format($aantal*$prijs,2);
$controlebedrag = number_format(str_replace(",", ".", $b),2);
if ($bedrag <> $controlebedrag):
echo "<br>ONGELIJK: ". $controlebedrag." <> ".$bedrag."=".$aantal."*".$prijs;
else:
echo "<br>GELIJK: ". $controlebedrag." = ".$bedrag."=".$aantal."*".$prijs;
endif;
?>

Current PHP version: 5.4.16
GELIJK: 9.87 = 9.87=3*3.29
number_format moet je alleen gebruiken in combinatie met "echo".

Je ziet nu dat je op regel 6 $prijs vult met een string. Bijvoorbeeld "3,98"

Vervolgens probeer je met die string een berekening te doen: $aantal * $prijs.

Daar grijpt php weer in.
PHP probeert nu in hoeverre de string als getal gezien kan worden. Van "3,98" blijft dan "3" over.

$aantal is ook 3, dus 3*3 = 9.

Dat resultaat (9) haal je weer door number_format() om er 9,00 van te maken.


Hoe jouw script dan toch 9,87 weet op te leveren????


[size=xsmall]Toevoeging op 25/06/2015 18:32:15:[/size]

edit:
ik zie dat je de "gebruikelijke" actie bij number_format() om een punt door een komma te vervangen hier niet toepast.

je misbruikt hier number_format() dus eigenlijk als round();
Als je van de vergelijking van floats

if ($bedrag <> $controlebedrag)

een vergelijking van strings maakt, dan gaat het wel goed:

if (''.$bedrag != ''.$controlebedrag)

Je overtreedt anders een van de regels voor floating-point logica: vergelijkingen van gelijkheden of ongelijkheden zijn bij floats onnauwkeurig en daardoor onbetrouwbaar.

Verder kun je de nauwkeurigheid op twee manieren opvoeren:

• Gebruik de BC Math-functies.

• Gebruik absolute getallen, dus integers, want die zijn wél nauwkeurig. Aangezien je met bedragen rekent, kun je die bijvoorbeeld met 1000 vermenigvuldigen, daarna je berekeningen uitvoeren en tot slot de uitkomsten weer door 1000 delen bij de weergave. (Met de nadruk op weergave, zoals Ivo ook zegt.)
Dank voor de oplossing,

Ik heb de BC_Math-functies toegepast.
Zonder de bcmul-functie in regel 7 valt ie ook in de GELIJK-tak, maar voor uniformiteit (en misschien wel noodzaak) ook hier de BC_Math_functies gebruikt.

Wat weten we samen toch veel !!!!!!!

<php?
echo 'Current PHP version: ' . phpversion();
$a = "3,29";
$b = "9,87";
$aantal = 3;
$prijs = str_replace(",", ".", $a);
$bedrag = bcmul($aantal, $prijs, 2);
$controlebedrag = str_replace(",", ".", $b);
$vergelijking = bccomp($bedrag, $controlebedrag, 2);
if (bccomp($bedrag, $controlebedrag, 2) <> 0):
echo "<br>ONGELIJK: ". $controlebedrag." <> ".$bedrag."=".$aantal."*".$prijs;
else:
echo "<br>GELIJK: ". $controlebedrag." = ".$bedrag."=".$aantal."*".$prijs;
endif;
?>

Current PHP version: 5.4.16
GELIJK: 9.87 = 9.87=3*3.29


[size=xsmall]Toevoeging op 26/06/2015 10:53:42:[/size]

Karel Bijvelds op 26/06/2015 10:52:56

Dank voor de oplossing,

Ik heb de BC_Math-functies toegepast.
Zonder de bcmul-functie in regel 7 valt ie ook in de GELIJK-tak, maar voor uniformiteit (en misschien wel noodzaak) ook hier de BC_Math_functies gebruikt.

Wat weten we samen toch veel !!!!!!!

<?php echo 'Current PHP version: ' . phpversion();
$a = "3,29";
$b = "9,87";
$aantal = 3;
$prijs = str_replace(",", ".", $a);
$bedrag = bcmul($aantal, $prijs, 2);
$controlebedrag = str_replace(",", ".", $b);
$vergelijking = bccomp($bedrag, $controlebedrag, 2);
if (bccomp($bedrag, $controlebedrag, 2) <> 0):
echo "<br>ONGELIJK: ". $controlebedrag." <> ".$bedrag."=".$aantal."*".$prijs;
else:
echo "<br>GELIJK: ". $controlebedrag." = ".$bedrag."=".$aantal."*".$prijs;
endif;
?>

Current PHP version: 5.4.16
GELIJK: 9.87 = 9.87=3*3.29



Reageren