Hallo,
Ik was bezig met een script tot ik steeds allerlei rare excepties terug kreeg die mijn script zelf had gegooid, omdat ik wilde voorkomen dat mijn script een getal groter dan 100 doorkreeg (om wat voor reden dan ook, niet interessant).

Het getal dat ik in het script gooide was echter niet groter dan 100, maar exact 100. Het getal is zo berekend:
var = 100 / 9
getal = 0
getal += var
getal += var
getal += var
getal += var
getal += var
getal += var
getal += var
getal += var
getal += var
Oftewel: (100 / 9) * 9. Reken zelf maar uit, dit geeft echt honderd (misschien geeft het 99.9999... op slechte rekenmachines). Ook in php zou deze berekening exact 100 geven, als je het met (100 / 9) * 9 doet. Als je 9 keer plus doet lijkt hij die in eerste instantie ook te geven (als je echo $getal doet komt er 100 op het scherm te staan). Als je nu echter deze vergelijking maakt: getal > 100, krijg je een 1 terug. Zeer tegenstrijdig dus.

Nu wil ik vragen: Zie ik iets over het hoofd, doe ik iets fout? En zo niet, kunnen jullie het probleem ook eens testen op jullie php-bak, om te kijken of het op iedere versie voorkomt? Hier is een snippet om het probleem te testen:
<?php
$number = 9;
echo 'Het getal = ' . $number . '. Het getal 100 wordt nu gedeeld door $number<br />';
$numberDivided = 100 / 9;
echo 'Het getal is gedeeld, en daar is deze uitkomst uitgekomen: ' . $numberDivided . '.<br />';
$numberProductByStar = $numberDivided * 9;
echo 'Het gedeelde getal is nu weer keer $number gedaan d.m.v. de *-operator. Uitkomst: ' . $numberProductByStar . '.<br />';
$numberProductByKruis = 0;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
$numberProductByKruis += $numberDivided;
echo 'Het gedeelde getal is nu weer keer $number gedaan door er 9 keer $numberDivided bij op te tellen. Uitkomst: ' . $numberProductByKruis . '.<br />';
echo 'Kijk of $numberProductByStar groter is dan 100: ';
echo $numberProductByStar > 100 ? 'Ja' : 'Nee';
echo '.<br />';
echo 'Kijk of $numberProductByKruis groter is dan 100: ';
echo $numberProductByKruis > 100 ? 'Ja' : 'Nee';
?>
Hier zou dit uit moeten komen (als de bug er niet is):
Het getal = 9. Het getal 100 wordt nu gedeeld door $number
Het getal is gedeeld, en daar is deze uitkomst uitgekomen: 11.111111111111.
Het gedeelde getal is nu weer keer $number gedaan d.m.v. de *-operator. Uitkomst: 100.
Het gedeelde getal is nu weer keer $number gedaan door er 9 keer $numberDivided bij op te tellen. Uitkomst: 100.
Kijk of $numberProductByStar groter is dan 100: Nee.
Kijk of $numberProductByKruis groter is dan 100: Nee

Als de bug er wel is dan moet de laatste nee Ja worden.

Als dit echt een bug blijkt te zijn zal ik hem submitten op de bug-track van php.net. Bedankt voor jullie hulp alvast.
Het is geen bug!!

100/9 is 11,1111111111111111111111111111 enzovoorts

Dat x negen (ik rond nu op meer decimalen af dan dat PHP dat doet) kom je op:
99,999999999999999999999999999999

Dat is uiteraard niet gelijk aan 100. Een rekenmachine rond vaak af en geeft dus inderdaad terug dat het 100 is (vanwege die afronding, als je de laatste 9 in het rijtje naar boven afrond, dan moet je bij alle negens 1 optellen, dan kom je op 100. Het principe van afronden)
Maar omdat een rekenmachine en PHP zelf ook al tussentijds aan afronden doet, kom je inderdaad niet op 100 uit, maar op die 99,999....

Hij rondt die echter zelf ook weer af en geeft 100 terug. -> Maar de eigenlijke waarde van die berekening (die 99,999...) houdt die wel vast. En 99,999.... is ongelijk aan 100. Vandaar dus, voor de weergave rondt die af.
Nee, dat komt waarschijnlijk door het steeds afronden na de berekening. En 9 minuscule afrondingen kunnen er net voor zorgen dat ie net boven de 100 komt.
@Robert Deiman: Dat klopt niet, want jij zegt nu dus dat het waarschijnlijk net even onder de 100 ligt. Zou kunnen, maar lijkt mij onwaarschijnlijk (de uitkomst is nu eenmaal 100 (als je hoofdrekent), en een goede rekenmachine geeft dat ook, en ik neem aan dat php een goede rekenmachine is :P).

Maar zelfs al is het zo, het gaat mij om een vergelijking of het getal boven de honderd komt, en niet onder...

@Santhe: Voorekenen (steeds afronden):

0 + 11.111111 = 11.111111 (afronden naar beneden)
11.111111 + 11.111111 = 22.222222 (afronden naar beneden)
22.222222 + 11.111111 = 33.333333 (afronden naar beneden)
33.333333 + 11.111111 = 44.444444 (afronden naar beneden)
44.444444 + 11.111111 = 55.555556 (afronden naar boven)
55.555556 + 11.111111 = 66.666667 (afronden naar boven niet nodig, want de laatst mogelijke decimaal is al 7)
66.666667 + 11.111111 = 77.777778 (afronden naar boven niet nodig, want de laatst mogelijke decimaal is al 8)
77.777778 + 11.111111 = 88.888889 (afronden naar boven niet nodig, want de laatst mogelijke decimaal is al 9)
88.888889 + 11.111111 = 100 (de laatste negen wordt nul, waardoor de een na laatste 8, 9 wordt + nog 1 die er bij op moet maakt 0, en zo wordt het honderd.

Dit zou dus ook exact honderd moeten maken.
Ik snap jou niet, 100 is niet groter dan 100. Je zou de vergelijking >= moeten maken.
@Orhan: Klopt, 100 is niet groter dan 100. En daarom vindt ik het raar dat PHP bij de door mij in de beginpost genoemde manier aangeeft dat 100 wel groter is dan 100 (oftewel, de ene 100 is net iets groter dan de andere 100).
@Lasse,

Waar zie jij dat staan?
Kijk of $numberProductByStar groter is dan 100: Nee.
Kijk of $numberProductByKruis groter is dan 100: Nee
@Orhan: Dat zie ik nergens staan. Als ik het script uitvoer krijg ik dit te zien:

Kijk of $numberProductByStar groter is dan 100: Nee.
Kijk of $numberProductByKruis groter is dan 100: Ja

De tekst die jij geeft zou je moeten te zien krijgen als de bug er niet is...
Hmm... Dit lijkt mij als 0,999..., wat gewoon 1 is, alleen met wat nulletjes meer. Bewijsstuk 1, Bewijsstuk 2.

Orhan daar gaat het nu niet om. Php beweerd dat het getal groter is dan honderd, dit is dus niet zo.

Mjin test:
Het getal = 9. Het getal 100 wordt nu gedeeld door $number
Het getal is gedeeld, en daar is deze uitkomst uitgekomen: 11.1111111111.
Het gedeelde getal is nu weer keer $number gedaan d.m.v. de *-operator. Uitkomst: 100.
Het gedeelde getal is nu weer keer $number gedaan door er 9 keer $numberDivided bij op te tellen. Uitkomst: 100.
Kijk of $numberProductByStar groter is dan 100: Nee.
Kijk of $numberProductByKruis groter is dan 100: Ja
Ik begreep het verkeerd , de tekst die ik gaf zag ik onderaan je post vandaar dat ik dacht dat dat goed ging. Speed reading is niet altijd goed zo te zien. ;)
edit

Foutje, ik las niet goed.


Ik heb het getest en inderdaad, hij geeft dat die 100 wordt, maar zegt wel dat die groter is dan 100, dat zou niet mogen. Er zijn 2 opties, of 99.9999 (kleiner dan 100) of precies gelijk aan 100.

Wat ik wel zei en wat blijkt te kloppen is dat die alleen de output afrond, en niet tussendoor.

Reageren