[PHP] 0 is niet 0

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • E-jey
  • Registratie: Juni 2001
  • Niet online
Voor de lol ben ik een perceptron aan het programmeren in PHP. Nu doet zich een vreemde situatie voor, ergens in de code doe ik 0.2 - 0.2. Daar zou dus 0 uit moeten komen, het antwoord is alleen -2.7755575615629E-17. En daar kan ik niet zoveel mee. Gekke is dat als ik er 1 bij optel het antwoord 1 is. Het is dus wel een soort van 0. Beide variabele zijn floats.

Gekke is dat dit wel werkt:
PHP:
1
2
3
        $test   = 0.2;
        $test2  = 0.2;
        $dump   = $test- $test2;


Alleen als ik de variabele uit mijn programma gebruik komt er opeens dat gekke getal uit. Als ik die variabele laat zien via var_dump() dan is het wel gewoon 0.2.

Ik hoop dat ik duidelijk ben. Iemand ervaring met dit probleem? Thanks

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Lees onze Getallen en talstelsels FAQ eens door en dan vooral "hoofdstuk" 13 en 14 ;)
Of kijk even deze video vanaf een minuut of 6:00

[ Voor 33% gewijzigd door RobIII op 31-12-2011 14:44 ]

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!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Dat is hoe floats (kunnen) werken, het is immers geen fixed getal ook al zou je dat soms wel verwachten.

edit: Grrrrr RobIII :P

[ Voor 11% gewijzigd door Cartman! op 31-12-2011 14:42 ]


Acties:
  • 0 Henk 'm!

  • E-jey
  • Registratie: Juni 2001
  • Niet online
Thanks, ik heb het even snel doorgekeken, klinkt wel logish. Wat is nu de netste oplossing? Ik kan er een if tussen zetten als het 0.2 is oid maar dat lijkt me niet gewenst. PHP kent geen decimal datatype.

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Gewoon alles met 10 vermenigvuldigen en bij je presentatie pas delen door 10, klaar.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoe kun je dat nou stellen als je niet eens weet met wat voor soort getallen de TS werkt?

@E-jey: waar je rekening mee moet houden is dat er afrondingsfouten in je berekeningen kunnen sluipen. Als je wilt testen of iets 0 is moet je dus niet kijken of het daadwerkelijk 0 is, maar of het ongeveer 0 is, binnen een bepaalde tolerantie.

Een goede methode om te kijken of $a gelijk is aan $b is door te doen:
abs($a - $b) <= (abs($a) + abs($b)) * $epsilon
met $epsilon een bepaalde fouttollerantie (zoals 1e-10)

[ Voor 71% gewijzigd door .oisyn op 31-12-2011 15:38 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Als je niet verder dan 2-3 getallen achter de komma wil hebben dan is de oplossing van Cartman! mogelijk. Wil je preciezer kunnen zijn, dan is BC Math een optie. Vergeet daarbij niet dat dat relatief traag is en dat bij veelvuldig gebruik best wel eens een merkbare vertraging zou kunnen opleveren.

edit:
Deze post heb ik getikt voordat ik .oisyn's edit zag. Zijn oplossing heeft (uiteraard) niet de nadelen die de stringconversie in BC math met zich meebrengt.

[ Voor 19% gewijzigd door NMe op 31-12-2011 15:37 ]

'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

.oisyn schreef op zaterdag 31 december 2011 @ 15:30:
Een goede methode om te kijken of $a gelijk is aan $b is door te doen:
Met dien verstande dat $a en $b wel domweg precies gelijk aan elkaar kunnen zijn. De float-representatie voor 0.2 is niet precies 0.2, maar wel altijd gelijk aan die van andere 0.2's (als je 2x 0.2 in je code zet). 't Is niet zo dat het de ene keer 0.2000...1 en de andere keer 0.2000...2 is. Dus als je invoer test op gelijkheid aan een bepaalde precieze waarde, dan is dat op zich wel te doen met domweg een ==-test. En dat is dan ook de reden dat het simpele scriptje in de startpost wel gewoon 0 oplevert.


Als het de uitkomst van een berekening is, dan is het uiteraard een ander verhaal, want het kan zijn dat je net iets meer of minder hebt afgetrokken/opgeteld/etc. En dan komt het hele float-verhaal natuurlijk wel om de hoek kijken.

Een minimale testcase is bijvoorbeeld zoiets:
$r = 0.3 - 0.2 - 0.1;

Acties:
  • 0 Henk 'm!

  • Snow_King
  • Registratie: April 2001
  • Laatst online: 08:40

Snow_King

Konijn is stoer!

.oisyn schreef op zaterdag 31 december 2011 @ 15:30:
Hoe kun je dat nou stellen als je niet eens weet met wat voor soort getallen de TS werkt?
In de basis is het geen raar voorstel.

Wij hebben bijvoorbeeld al onze prijzen in centen in de database staan, verwerken alles intern ook in centen pas totdat het ergens op een factuur moet.

Je kan toch het beste proberen floats te vermijden imho, maar pas op het laatste moment van die integer naar de float gaan.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Snow_King schreef op zondag 01 januari 2012 @ 11:52:
In de basis is het geen raar voorstel.
Het is geen raar voorstel, maar oisyn heeft natuurlijk ook gelijk: hoe wil je dat dan doen in een physics simulatie bijvoorbeeld, waar de getallen van 10^-10 tot 10^10 gaan? :)

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 12-09 10:43

Ventieldopje

I'm not your pal, mate!

Is dit niet gewoon wat je wil? http://www.php.net/manual/en/function.bcsub.php

PHP:
1
bcsub('0.2', '0.2');

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Mogelijk wel, maar gelukkig heb ik dat hierboven ook al geopperd inclusief de bijbehorende potentiële problemen. ;)

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

  • E-jey
  • Registratie: Juni 2001
  • Niet online
Het probleem is inmiddels opgelost en ik heb er ook nog wat van geleerd. Bedankt voor de reacties en nog de beste wensen.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Snow_King schreef op zondag 01 januari 2012 @ 11:52:
[...]
In de basis is het geen raar voorstel.
Je leest niet wat ik zeg. In de basis is het juist wél een raar voorstel. Het is pas geen raar voorstel in specifieke gevallen, zoals jouw voorbeeld met centen. Het enige wat de TS hier heeft laten weten is dat hij een probleem heeft met 0.2. Waar die 0.2 vandaan komt blijkt nergens uit. En met een beetje meer onderzoek naar z'n onderwerp (perceptrons) kom je erachter dat het gaat om waarden tussen 0 en 1.
Je kan toch het beste proberen floats te vermijden imho, maar pas op het laatste moment van die integer naar de float gaan.
Complete nonsens. Floating point getallen zijn prima te gebruiken, maar je moet ze wel voor floating point getallen gebruiken, en niet voor fixed point zoals geldbedragen. Puur het feit dat jij nog geen goede use case bent tegengekomen wil nog niet zeggen dat men ze dan maar beter moet vermeiden :)

[ Voor 6% gewijzigd door .oisyn op 01-01-2012 23:31 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1