[PHP] rekenfout in PHP

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • hommer
  • Registratie: September 2000
  • Laatst online: 15-09 15:23
Oke, 't lijkt zo misschien niet de meest nuttige code, maar ik verbaas me nogal over een fout die PHP lijkt te maken.

code:
1
2
3
$float = 336.52;
$float = ($float - floor($float))*100;
echo $float;

Geeft me dit: 51.999999999998

Ik heb een beetje zitten zoeken her en der maar ik kan alleen een onduidelijke duitse posting ergens vinden die me niet het inzicht geeft dat ik hoop.
Heeft iemand enig idee hoe dit kan?

t.k.a. sig space t.e.a.b.


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

dat heet floating precision; oftewel: floats zijn nooit precies ;)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Jk_W
  • Registratie: Februari 2003
  • Niet online

Jk_W

I Think...

Maar wat kan er nou niet precies zijn aan ($float - floor($float))?
Dat is in dit geval toch gewoon 0.52000000 ?

Hij maakt daar toch niet opeens een ander getal van?

*me begrijpt dit "foutje" ook niet.

Acties:
  • 0 Henk 'm!

  • hommer
  • Registratie: September 2000
  • Laatst online: 15-09 15:23
Floating point precision...? Ik kan me niet voorstellen dat die met zo'n simpel scriptje al zo z'n kop op steekt. :?

t.k.a. sig space t.e.a.b.


Acties:
  • 0 Henk 'm!

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 15-09 18:24

dusty

Celebrate Life!

Dit gebeurt dan ook niet alleen bij PHP ;) Maar is dus een bijwerking van de specificatie hoe een float wordt opgeslagen.

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


Acties:
  • 0 Henk 'm!

  • robbert
  • Registratie: April 2002
  • Laatst online: 21-09 20:37
Bij mij komt er overigens wel 52 uit ;)

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

hommer schreef op dinsdag 15 februari 2005 @ 23:20:
Floating point precision...? Ik kan me niet voorstellen dat die met zo'n simpel scriptje al zo z'n kop op steekt. :?
Waarom niet? De uitkomst van je floor functie levert een integer, maar omdat die integer afgetrokken wordt van een float, wordt deze intern ook naar een float gecast, waardoor je twee floats van elkaar aftrekt, en je dus blijkbaar gezever krijgt. Wil je dat niet, dan zul je zelf af moeten gaan ronden. :)

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

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

In windows op mijn Athlon XP 2100+ komt er 51.999999999998 uit, in Linux op mijn Athlon 850 komt er 52 uit... Het is dus naast variabel in de specificaties, ook nog eens variabel per platform (zowel OS als hardware kan uitmaken) :/

Floating point is dan ook lang niet altijd even geschikt voor precisie-berekeningen zoals al eerder gesuggereerd werd.

Acties:
  • 0 Henk 'm!

  • HunterPro
  • Registratie: Juni 2001
  • Niet online
zorgen dat nadat je een float hebt gebruikt je die afrondt naar het aantal decimalen dat je daadwerkelijk nodig hebt :)

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

HunterPro schreef op dinsdag 15 februari 2005 @ 23:30:
zorgen dat nadat je een float hebt gebruikt je die afrondt naar het aantal decimalen dat je daadwerkelijk nodig hebt :)
Dat is ook niet altijd even wenselijk; wanneer je dat bij tussenstappen zou doen, verlies je juist soms nog meer preciesie. :)

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

  • hommer
  • Registratie: September 2000
  • Laatst online: 15-09 15:23
HunterPro schreef op dinsdag 15 februari 2005 @ 23:30:
zorgen dat nadat je een float hebt gebruikt je die afrondt naar het aantal decimalen dat je daadwerkelijk nodig hebt :)
Tja, die oplossing had ik ook al bedacht, floor -> round($float,2) en 't gaat weer prima. Maar ja, 't ging me om het idee.
Wat die opslag betreft; hoe wordt een float opgeslagen?

t.k.a. sig space t.e.a.b.


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

hommer schreef op dinsdag 15 februari 2005 @ 23:33:
Tja, die oplossing had ik ook al bedacht, floor -> round($float,2) en 't gaat weer prima. Maar ja, 't ging me om het idee.
Wat die opslag betreft; hoe wordt een float opgeslagen?
Op het laagste niveau? Gewoon als een binaire waarde lijkt me, net als elke andere variabele. ;)

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

  • Jk_W
  • Registratie: Februari 2003
  • Niet online

Jk_W

I Think...

Is het dus wenselijker om "double" te gebruiken? Of blijft het feit hier dan mee bestaan?

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
ACM schreef op dinsdag 15 februari 2005 @ 23:27:
In windows op mijn Athlon XP 2100+ komt er 51.999999999998 uit, in Linux op mijn Athlon 850 komt er 52 uit... Het is dus naast variabel in de specificaties, ook nog eens variabel per platform (zowel OS als hardware kan uitmaken) :/
Volgens mij is het alleen afhankelijk van de compiler en niet van de hardware (als die zich aan een bepaalde standaard voor floating point getallen houdt).

Ik denk dat het niet eens van de compiler, maar van de library die het getal op je scherm weergeeft afhangt.

[ Voor 11% gewijzigd door Olaf van der Spek op 15-02-2005 23:44 ]


Acties:
  • 0 Henk 'm!

  • ludo
  • Registratie: Oktober 2000
  • Laatst online: 26-04-2024
Ik vraag me af waar TS een 'beetje' heeft gezocht. Niet in de PHP manual waarschijnlijk, want daar staat dit probleem bij floats duidelijk in de manual:
It is quite usual that simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a little loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8 as the result of the internal representation really being something like 7.9999999999....

This is related to the fact that it is impossible to exactly express some fractions in decimal notation with a finite number of digits. For instance, 1/3 in decimal form becomes 0.3333333. . ..

So never trust floating number results to the last digit and never compare floating point numbers for equality. If you really need higher precision, you should use the arbitrary precision math functions or gmp functions instead.
Hier staan ook tips voor als je meer precisie nodig hebt. Dit kan door bijvoorbeeld de bcmath functies te gebruiken. Zie dus: http://nl2.php.net/manual/en/language.types.float.php

Acties:
  • 0 Henk 'm!

  • HunterPro
  • Registratie: Juni 2001
  • Niet online
-NMe- schreef op Tuesday 15 February 2005 @ 23:32:
[...]

Dat is ook niet altijd even wenselijk; wanneer je dat bij tussenstappen zou doen, verlies je juist soms nog meer preciesie. :)
mijn wiskundeleraar heeft me altijd geleerd dat je pas aan het einde mag afronden ;-)

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Dit probleem heeft niks met PHP, platform, CPU of whatever te maken. Het is gewoon inherent aan Floating point's.
A floating-point calculation is an arithmetic calculation done with floating-point numbers and often involves some approximation or rounding because the result of an operation may not be exactly representable.
Fracties zijn binair (in 1-en en 0-en dus) niet altijd exact op te slaan. Met floating points kom je een heel eind, maar uiteindelijk blijft het een benadering. Zie ook de IEEE Floating Point Standaard of google er effe naar

Er zijn dus (zoals aangegeven) wel wat libraries die nog meer preciesie bieden (en sommige misschien wel 100%?) maar of dat optimaal is is een tweede. Tevens is het wel een beetje afhankelijk van hoe je platform en/of compiler met floating points om gaat, maar dat is niet het punt hier. Floating points zijn (zover ik weet) dus nooit precies.

[ Voor 100% gewijzigd door RobIII op 16-02-2005 04:12 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • hommer
  • Registratie: September 2000
  • Laatst online: 15-09 15:23
ludo schreef op Tuesday 15 February 2005 @ 23:51:
Ik vraag me af waar TS een 'beetje' heeft gezocht. Niet in de PHP manual waarschijnlijk, want daar staat dit probleem bij floats duidelijk in de manual:
[...]
Hier staan ook tips voor als je meer precisie nodig hebt. Dit kan door bijvoorbeeld de bcmath functies te gebruiken. Zie dus: http://nl2.php.net/manual/en/language.types.float.php
Had ik inderdaad nog niet gevonden (wel gezocht, maar blijkbaar niet lang genoeg). Dank!

t.k.a. sig space t.e.a.b.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:05
ACM schreef op Tuesday 15 February 2005 @ 23:27:
In windows op mijn Athlon XP 2100+ komt er 51.999999999998 uit, in Linux op mijn Athlon 850 komt er 52 uit... Het is dus naast variabel in de specificaties, ook nog eens variabel per platform (zowel OS als hardware kan uitmaken) :/
Hoewel je in principe verschillende manieren hebt om floating point getallen te representeren zit in de praktijk in alle desktop en serversystemen dezelfde IEEE-compatible functionaliteit. Die functionaliteit is ook onafhankelijk van het gebruikte besturingssysteem, omdat de applicatie de floating point processor direct aanstuurt (daar heeft het besturingssysteem in beginsel niets mee te maken).

Verder is het heel simpel: 0.52 is niet exact te representeren, dus dat wordt intern altijd iets van 0.519999999998. Als je dit getal vervolgens weergeeft dan is die weergave wel platformafhankelijk (dat hoeft natuurlijk niet, maar in PHP blijkbaar wel) waardoor soms wel en soms niet wordt afgerond.
Pagina: 1