1 + 2 = 3, maar 0.1 + 0.2 is NIET 0.3. Vreemd of niet?

Ingediend door Dirk Hornstra op 07-feb-2019 22:38

Als software engineer die zich op verschillende terreinen bezig houdt met zijn vakgebied kan ik vaak lachen om de tweets van het account iamdeveloper en daar kwam ik deze tweet tegen: link. Je ziet dat daarin gezegd wordt dat in javascript 0.1 + 0.2 === 0.3 de waarde "false" geeft, terwijl je een "true" zou verwachten. Hoewel ik deze had kunnen retweeten met "wat dom van Javascript!" ben ik eerst eens in de reacties gaan kijken. En dan is het goed om te lezen dat er niet alleen haat-accounts op Twitter bestaan maar ook mede-developers/nerds die wél weten hoe het zit. Want zij verwijzen naar de IEEE 754 specificatie die dit zou veroorzaken.

Ik ben eerst eens gaan kijken of de bewering echt klopt. In Chrome open je even de console (<CTRL> <SHIFT> en i toets indrukken) en in de console voer je in: 0.1 + 0.2
Je krijgt in de regel daaronder meteen al het resultaat te zien: 0.30000000000000004. Ok, er gebeurt dus iets wat je niet verwacht. Het is natuurlijk niet alleen bij dit getal. Ook als ik 0.1 + 0.11 invoer krijg ik 0.21000000000000002 te zien. Dit verklaart wel iets waar ik zelf tegenaan gelopen ben. Ik heb namelijk een soort digitaal kasboek gemaakt, responsive site met bootstrap waar uit uitgaven in bij kan houden. Bovenin vul ik het totaalbedrag, per blokje eronder kan ik specificeren waar het aan uitgegeven is (50 euro bij de shell, 45 euro benzine, 3.50 voor de redbull, 1.50 voor king pepermunt). Als ik een blokje vul wordt er automatisch een nieuw blokje gemaakt met het resterende bedrag. Maar bij sommige bedragen bleven de blokjes maar doorgaan, terwijl ik volgens de kassabon allang op het totaalbedrag zat.

Op zich is het ook weer niet heel verwonderlijk. Je werkt met "floating point" getallen, zoals de term al zegt met een "zwevende komma getal". In een vast aantal bytes wordt een verscheidenheid aan getallen opgeslagen. Maar daarbij heb je (dus) afrondingsfouten. Misschien ben je het ook wel eens in Excel of een databasetabel tegengekomen, dat je ineens niet meer dat getal hebt (bijvoorbeeld 1), maar een getal 1.000001E-12.

Ik ben eerst even gaan kijken naar die specificatie van IEEE 754 en kom bij Google pas op pagina 2 deze URL tegen: https://standards.ieee.org/standard/754-1985.html

Dat lijkt de juiste pagina te zijn, maar je kunt daar niet de specs bekijken/downloaden. Je moet inloggen, een account aanmaken of "buy this standard". Ok... ik ben RFC's gewend, waarin de boel gewoon in een tekstbestandje uitgewerkt staat. Ik begrijp waarom Google dit resultaat dus niet zo relevant vindt. 

Beter is de wikipedia-pagina over floating point getallen: link en de wikipedia-pagina over IEEE 754: link. Maar dan drop ik hier ook meteen even de URL's die in die wikipedia-pagina's genoemd worden én die in de comments op de tweet staan, want ook die geven meer inzicht. En nu weet ik niet of het nu bij mijn accountancy-opleiding of ook al bij mijn Hogere Informatica opleiding het punt was om "het dan in centen te rekenen". Dus niet 0.50 maar 50 cent. Misschien dat ik dat maar eens als leidraad moet nemen om mijn "online-kasboek" te fixen!

https://floating-point-gui.de/

https://0.30000000000000004.com/

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

https://people.eecs.berkeley.edu/~wkahan/JAVAhurt.pdf

2008-standard: https://standards.ieee.org/content/ieee-standards/en/standard/754-2008.html

https://www.youtube.com/watch?v=PZRI1IfStY0