[PHP] Hoe komt dit zo onnauwkeurig?

Pagina: 1
Acties:

  • creative8500
  • Registratie: September 2001
  • Laatst online: 03-01 16:54
PHP:
1
2
3
4
5
6
7
8
9
10
<?
    $x = 1;
    while($x !== 5)
    {
                $g = 0.1;
                $x = $x+$g;
                if($x == 5){die;}
        echo $x."<br>";
    }
?>

Het script klopt van geen kant, het doet niet wat ik wil enz., maar daar gaat het niet om.

Hij blijft dus getalletjes spugen, en toen ik eventjes scrollde zag ik dit:
code:
1
2
3
4
5
6
7
8
9
53.9
54
54.1
54.200000000001
54.300000000001
54.400000000001
54.500000000001
54.600000000001
54.700000000001

En nog meer verderop:
code:
1
2
3
4
5
6
7
8
9
10
11
12
1259.1
1259.2
1259.3
1259.4
1259.5
1259.5999999999
1259.6999999999
1259.7999999999
1259.8999999999
1259.9999999999
1260.0999999999
1260.1999999999

Hoe komt dit zo onnauwkeurig :?

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:14
onnauwkeurig? :?

Er zal een functie bestaan waarmee je kan gaan bepalen tot op hoeveel decimalen er moet afgerond worden.

https://fgheysels.github.io/


  • D2k
  • Registratie: Januari 2001
  • Laatst online: 31-08 10:19

D2k

round() bijvoorbeeld

Doet iets met Cloud (MS/IBM)


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
komt omdat die getallen niet precies gerepresenteerd kunnen worden in het binaire stelsel, net als 1/3 in het 10-tallig stelsen.

je kunt het oplossen door number_format te gebruiken voordat je de getallen print.

[edit]foutje gefixed :)

  • creative8500
  • Registratie: September 2001
  • Laatst online: 03-01 16:54
Maar als ik 54.1+0.1 doe dan hoort er toch geen 54.200000000001 uit te komen :?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ik ga dit nu voor de zoveelste keer tikken, maar ik doe het met liefde ;) .

Hier worden niet decimale berekeningen gebruikt. Daarbij krijg je dergelijke vervelende, maar kleine verschillen die vaak insignificant zijn...

Als je echt exacte berekeningen nodig hebt (zoals in scheidkundige, natuurkundige, boekhoudkundige appklicaties) moet je decimale berekeningen gebruiken. Of die standaard ergens in de PHP library zitten weet ik echter niet :) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • creative8500
  • Registratie: September 2001
  • Laatst online: 03-01 16:54
Ok, thx :)

  • JF_
  • Registratie: Juni 2001
  • Laatst online: 03-09 15:28

JF_

1 foutje zie ik nu al... Als je 'x niet gelijk aan 5' bedoelt moet je x!=5 hebben. Dus geen !==....

  • JF_
  • Registratie: Juni 2001
  • Laatst online: 03-09 15:28

JF_

Op woensdag 30 januari 2002 20:51 schreef marcusk het volgende:
komt omdat die getallen niet precies gerepresenteerd kunnen worden in het decimale stelsel, net als 1/3 in het 10-tallig stelsen.
In het decimale stelsel werkt 0.1 juist wel... Je bedoelt 't binaire stelsel. Alle breuken moeten opgebouwd worden uit 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, enz...

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op woensdag 30 januari 2002 20:56 schreef JF_ het volgende:

[..]

In het decimale stelsel werkt 0.1 juist wel... Je bedoelt 't binaire stelsel. Alle breuken moeten opgebouwd worden uit 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, enz...
ik bedoelde idd het binaire stelsel, foutje.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op woensdag 30 januari 2002 20:53 schreef JF_ het volgende:
1 foutje zie ik nu al... Als je 'x niet gelijk aan 5' bedoelt moet je x!=5 hebben. Dus geen !==....
dat is een beetje vaag idd, maar niet fout, zie http://php.nederland.net/manual/en/language.operators.comparison.php. het enige verschil tussen != en !== is dus dat de laatste ook het type checkt.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
cREATiVe8500, het vergelijken van je getallen kun je beter zo doen (bv) :
PHP:
1
2
3
<?
if (round($x * 10) != 50)
?>

dan zou het wel moeten werken.

je kunt ook overwegen om te werken met het 10-voud van je getallen (en er dus steeds 1 bij op te tellen ipv 0.1), en pas als je ze echt gebruikt weer te delen door 10 (en afronden met number_format als je ze print). dan heb je dit probleem niet. het zou ook wel eens sneller kunnen zijn.

  • elnino
  • Registratie: Augustus 2001
  • Laatst online: 03-09 05:13
Op woensdag 30 januari 2002 20:46 schreef cREATiVe8500 het volgende:
Hij blijft dus getalletjes spugen, en toen ik eventjes scrollde zag ik dit:
code:
1
2
3
4
5
6
7
8
9
53.9
54
54.1
54.200000000001
54.300000000001
54.400000000001
54.500000000001
54.600000000001
54.700000000001
Dit heeft ermee te maken dat de + en de - niet altijd even goed optellen en aftrekken. (Ik dacht dat er zoiets ook in de PHP manual stond, kon het zo snel niet vinden) Als je echt precieze berekingen nodig hebt, kun je de BCMath-functies gebruiken. Deze moeten wel meegecompileerd zijn. Als je niet zo exact hoeft te zijn, kun je ook round() gebruiken, omdat het om kleine verschillen gaat (0,0000000000001 e.d.).

  • Grum
  • Registratie: Juni 2001
  • Niet online
Op woensdag 30 januari 2002 20:46 schreef cREATiVe8500 het volgende:
[..snip..]
even wat info over '!=='
$a !== $b
Not identical TRUE if $a is not equal to $b, or they are not of the same type. (PHP 4 only)
http://www.php.net/manual/en/language.operators.comparison.php

in het begin is $x een int (je assigned gewoon 1) als jij vervolgens elke keer 0.1 (float/double) erbij op gaat tellen klopt het type dus al niet meer en zal de loop fijn permanent doorgaan (as u might have noticed)

  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

Paar tips
PHP:
1
2
3
4
5
6
7
8
9
10
<?
   
 $x = 1;   
 while($x !<= 5) // VERANDER !== IN !<= OF ALS DAT NIET KAN IN <=
 {              
   $x .= 0.1;
   if($x >= 5){ die; } // VERANDER == IN >=
   echo round($x)."<br>"; // VOER round() TOE
 }
?>

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • Rense Klinkenberg
  • Registratie: November 2000
  • Laatst online: 23:45
Er is op de php newsgroep wel eens een thread over geweest. daar bleek ook uit dat het eigenlijk niet veilig is om berekeningen met valuta-waarden te doen, omdat er met floating point berekeningen altijd wel eens iets mis kan gaan.

Het advies voor valuta-berekeningen was om de waarde met 100 te vermenigvuldigen, zodat het een gewone integer wordt, waarmee php wel perfect kan rekenen.

* Rense Klinkenberg kan de thread helaas niet meer vinden.

  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 22:43

Pelle

🚴‍♂️

Op donderdag 31 januari 2002 22:13 schreef freak007 het volgende:
Het advies voor valuta-berekeningen was om de waarde met 100 te vermenigvuldigen, zodat het een gewone integer wordt, waarmee php wel perfect kan rekenen.
Cool, ik zal het onthouden. Ben bezig met een grote B2B-shop, en ik liep vanmiddag ook al tegen wat onnauwkeurigheids foutjes aan.

En inderdaad, number_format() is je vriend (thnks Gordijnstok :)).
Pagina: 1