{"id":147,"date":"2015-09-25T18:36:36","date_gmt":"2015-09-25T18:36:36","guid":{"rendered":"http:\/\/techblog.auchmonoabspielbar.de\/?p=147"},"modified":"2015-09-26T18:37:25","modified_gmt":"2015-09-26T18:37:25","slug":"fliesskommazahlen-und-unfaehige-programmierer","status":"publish","type":"post","link":"http:\/\/techblog.auchmonoabspielbar.de\/?p=147","title":{"rendered":"Flie\u00dfkommazahlen und unerfahrene Programmierer"},"content":{"rendered":"<p>Gestern habe ich auf slashdot.org ein Beitrag eines Programmierers gesehen, der sich dar\u00fcber beklagt hat, dass von ihm verlangt wurde, eine Steuerberechnung mit JavaScript zu entwickeln. Schlie\u00dflich kennt JavaScript nur Flie\u00dfkommazahlen und &#8222;jeder&#8220; wei\u00df, dass man damit keine kaufm\u00e4nnischen Anwendungen schreiben kann.<\/p>\n<p>Diese Meinung ist weit verbreitet &#8211; gerade in diesen Kreisen. Das weckt bei mir den Argwohn, ob im Bereich kaufm\u00e4nnischer Software verst\u00e4rkt m\u00e4\u00dfig erfahrene Programmierer unterwegs sind? Und aus solchen Vorurteilen und mangelnden Wissen resultieren dann BCD Arithmetik-Libraries und BCD Befehle in Prozessoren (BCD = binary coded decimal &#8211; zwei Dezimalziffern 0-9 und 0-9 in einem Byte).<\/p>\n<p>Das ist totaler Unfug und zeigt nur einen erheblichen Mangel an (mathematischen) Wissen.<\/p>\n<p><strong>Mythos 1: im Bin\u00e4rsystem kann man Zahlen nicht exakt darstellen, im Dezimalsystem schon.<\/strong><br \/>\nFast v\u00f6lliger Unsinn. Es wird immer der Wert 0.1 (als Bruch: 1\/10) als Beispiel genommen. Dieser Wert ist im Bin\u00e4rsystem tats\u00e4chlich nur gerundet darzustellen, da er dort eine unendliche Periode besitzt. Aber solche Zahlen gibt es im Dezimalsystem auch: 1\/3. Dieser Wert l\u00e4sst sich Dezimal auch nur gerundet darstellen. Prinzipiell gilt f\u00fcr (teilerfremde) Br\u00fcche der Art p\/q, dass sie eine periodische Darstellung haben, wenn q Primfaktoren besitzt, die in der Basis nicht vorkommen. Das Bin\u00e4rsystem hat nur den Primfaktor 2 in der Basis &#8211; wirklich nicht \u00fcppig. Im Dezimalsystem sind es 2 und 5 &#8211; auch nicht wirklich besser. 1\/3 &#8211; 1\/7 &#8211; 1\/11 &#8211; 1\/13&#8230; verdammt viele Br\u00fcche erzeugen in beiden Systemen eine periodische Darstellung. <\/p>\n<p>Das Problem lie\u00dfe sich hier noch l\u00f6sen, indem man mit Rationalen Zahlen arbeitet. Das hat aber Grenzen, denn man kann niemanden eine Rechnung schicken, auf der 47\/11 Euro gefordert werden. Auf der Rechnung werden also doch nur 4,272727272727272727272727272727&#8230; Euro oder gerundet 4,27 Euro auftauchen.<\/p>\n<p><strong>Mythos 2: mit Flie\u00dfkommazahlen kann man nicht Cent-genau rechnen<\/strong><br \/>\nEine double Flie\u00dfkommazahl (wie sie z.B. von JavaScript verwendet wird) besitzt \u00fcber 50 Bit f\u00fcr die Mantisse. Das sind mehr als 15 Dezimalstellen. Damit kann man mehr als nur das gesamte Geld dieser Welt auf einen Cent genau darstellen. Man muss lediglich darauf achten, den Flie\u00dfkommawert bei der Ausgabe zum n\u00e4chsten Cent hin auf- oder abzurunden.<\/p>\n<p>Wenn die NASA mit Flie\u00dfkommaberechnungen Satelliten auf Milliarden Kilometer genau steuern kann, dann sollte auch ein m\u00e4\u00dfig begabter Programmierer in der Lage sein, eine Leberwurst und 200 Gramm Butter abzurechnen. Das ist keine Raketenwissenschaft.<\/p>\n<p><strong>Mythos 3: wenn ich Integer-Werte f\u00fcr Cent-Betr\u00e4ge verwende, habe ich keine Rundungsfehler<\/strong><br \/>\nDas gilt nur, wenn man sich auf simple Addition, Subtraktion oder Multiplikation beschr\u00e4nkt. Sobald eine Division ins Spiel kommt, ist der Vorteil dahin (ab hier sind es rationale Zahlen). Sieben Prozent Mehrwertsteuer auf mein Buch f\u00fcr 43,21 Euro sind 3,0247 Euro. Nat\u00fcrlich kann ich auch in hundertstel-Cent statt Cent rechnen. Aber das verschiebt das Problem nur und l\u00f6st es nicht prinzipiell. Sobald ich den Betrag \u00fcber eine Split-Buchung auf drei Kostenstellen aufteile, ist es mit exakten Werten vorbei.<\/p>\n<p><strong>Mythos 4: in einer Rechnung m\u00fcssen alle Betr\u00e4ge auf den Cent genau stimmen<\/strong><br \/>\nDas funktioniert nur, wenn man gen\u00fcgend ungenau hinschaut. Wenn ich auf einer Rechnung die gerundeten Mwst-Betr\u00e4ge zu jeder Rechnungsposition ausweise, wird die Summe der Betr\u00e4ge nur zuf\u00e4llig exakt zum gerundeten Mwst-Betrag der Netto Summe passen. Das Finanzamt wei\u00df das. Jeder vern\u00fcnftige Kaufmann ebenfalls. Und ein Programmierer sollte das auch wissen.<\/p>\n<p><strong>Fazit: man kann auch kaufm\u00e4nnische Software mit Flie\u00dfkommazahlen erstellen<\/strong><br \/>\nEs m\u00fcssen halt einfach ein paar Rahmenbedingungen beachtet werden. Alle Ausgabewerte sollten auf den n\u00e4chsten Cent auf- oder abgerundet werden. Sonst passieren so Dinge wie &#8222;\u00fcberweisen Sie 4,272727272727273 Euro auf unser Konto&#8220;. Das ist immer f\u00fcr einen Lacher gut, aber genau genommen ist nichts schlimmes passiert. Der Betrag ist unhandlich aber nicht so falsch, dass ein messbarer Schaden entsteht. <\/p>\n<p>Man kann einen Flie\u00dfkommawert nicht unbesehen als Schleifenz\u00e4hler verwenden. Dann kann es zu den gef\u00fcrchteten &#8222;one off&#8220; Fehlern kommen, die Schleife l\u00e4uft einmal zu oft oder zu wenig. Auch hier muss man mit einer geeigneten Skalierung und Rundung arbeiten &#8211; dann geht das sehr wohl.<\/p>\n<p>Bei extrem unterschiedlichen Werten kann die Reihenfolge der Berechnung f\u00fcr das Ergebnis wichtig sein: (1.001 * 10 hoch 15 + 0.00000001) &#8211; 1.0005 * 10 hoch 15 wird ein anderes Ergebnis liefern als (1.001 * 10 hoch 15 &#8211; 1.0005 * 10 hoch 15) + 0.00000001. So etwas kommt in der Physik und in der Mathematik durchaus vor. In kaufm\u00e4nnischen Anwendungen hat man so eine Dynamik eher nicht.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gestern habe ich auf slashdot.org ein Beitrag eines Programmierers gesehen, der sich dar\u00fcber beklagt hat, dass von ihm verlangt wurde, eine Steuerberechnung mit JavaScript zu entwickeln. Schlie\u00dflich kennt JavaScript nur Flie\u00dfkommazahlen und &#8222;jeder&#8220; wei\u00df, dass man damit keine kaufm\u00e4nnischen Anwendungen schreiben kann. Diese Meinung ist weit verbreitet &#8211; gerade in diesen Kreisen. Das weckt bei [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-147","post","type-post","status-publish","format-standard","hentry","category-software"],"_links":{"self":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts\/147","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=147"}],"version-history":[{"count":5,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts\/147\/revisions"}],"predecessor-version":[{"id":152,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts\/147\/revisions\/152"}],"wp:attachment":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=147"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}