Ich schaute http://www.joelonsoftware.com/items/2011/06/27.html und lachte über Jon Skeets Witz, dass 0,3 nicht 0,3 ist. Ich persönlich hatte nie Probleme mit Floats / Decimals / Doubles, aber dann erinnere ich mich, dass ich 6502 sehr früh gelernt habe und in den meisten meiner Programme keine Floats benötigt habe. Das einzige Mal, dass ich es verwendete, war für Grafik und Mathematik, wo ungenaue Zahlen in Ordnung waren und die Ausgabe für den Bildschirm und nicht zum Speichern (in einer Datenbank, Datei) oder abhängig von.
Meine Frage ist, wo sind Orte, an denen Sie normalerweise floats / decimals / double verwenden? Also muss ich auf diese Fallstricke achten. Mit Geld benutze ich Longs und speichere Werte in Cent-Schritten. Für die Geschwindigkeit eines Objekts in einem Spiel addiere ich Ints und dividiere (oder Bitverschiebung) den Wert, um zu wissen, ob ich ein Pixel verschieben muss oder nicht. (Ich habe in den 6502 Tagen einen Objektzug gemacht, wir hatten keine Teilung und keine Schwimmbewegungen, aber wir hatten Verschiebungen).
Also war ich meistens neugierig.
quelle
Antworten:
Denn sie sind für die meisten Zwecke, mehr genauer als ganze Zahlen.
Nun, wie ist das? "für die Geschwindigkeit eines Objekts in einem Spiel ..." Dies ist ein gutes Beispiel für einen solchen Fall. Angenommen, Sie benötigen einige sehr schnelle Objekte, z. B. Kugeln. Um ihre Bewegung mit ganzzahligen Geschwindigkeitsvariablen beschreiben zu können, müssen Sie sicherstellen, dass die Geschwindigkeiten im Bereich der ganzzahligen Variablen liegen, dh, Sie können kein beliebig feines Raster haben.
Dann möchten Sie vielleicht auch einige sehr langsame Objekte beschreiben, z. B. den Stundenzeiger einer Uhr. Da dies ungefähr 6 Größenordnungen langsamer ist als die Aufzählungsobjekte, sind die ersten ld (10⁶) ≈ 20 Bits Null, was
short int
Typen von Anfang an ausschließt. Ok, heute haben wirlong
s überall, was uns noch komfortable 12 Bits lässt. Aber auch dann ist die Taktrate nur auf vier Dezimalstellen genau. Das ist keine sehr gute Uhr ... aber für ein Spiel ist es auf jeden Fall in Ordnung. Nur möchten Sie das Raster nicht viel gröber machen, als es bereits ist.... was zu Problemen führt, wenn Sie eines Tages einen neuen, noch schnelleren Objekttyp einführen möchten. Es ist keine "Kopffreiheit" mehr vorhanden.
Was passiert, wenn wir uns für einen Float-Typ entscheiden? Gleiche Größe von 32 Bit, aber jetzt haben Sie für alle Objekte volle 24 Bit Genauigkeit . Das heißt, die Uhr hat genug Präzision, um jahrelang sekundengenau synchron zu bleiben. Die Kugeln haben keine höhere Präzision, aber sie "leben" sowieso nur für Bruchteile einer Sekunde, so dass es völlig nutzlos wäre, wenn sie dies getan hätten. Und Sie geraten nicht in Schwierigkeiten, wenn Sie noch viel schnellere Objekte (warum nicht Lichtgeschwindigkeit? Kein Problem) oder viel langsamere Objekte beschreiben möchten. Sie werden solche Dinge in einem Spiel sicher nicht brauchen, aber Sie tun es manchmal in Physiksimulationen.
Und mit Gleitkommazahlen erhalten Sie immer die gleiche Genauigkeit, ohne zuerst ein nicht offensichtliches Raster auswählen zu müssen. Das ist vielleicht der wichtigste Punkt, da solche Auswahlnotwendigkeiten sehr fehleranfällig sind.
quelle
Sie verwenden sie, wenn Sie einen stetigen Wert und keinen diskreten Wert beschreiben . Es ist nicht komplizierter zu beschreiben. Machen Sie einfach nicht den Fehler, einen Wert mit einem Dezimalpunkt als stetig anzunehmen. Wenn sich alles auf einmal in Stücken ändert, wie das Hinzufügen eines Pennys, ist es diskret.
quelle
Sie haben hier wirklich zwei Fragen.
Warum braucht überhaupt jemand Gleitkomma-Mathematik?
Wie Karl Bielefeldt betont, können Sie mit Gleitkommazahlen kontinuierliche Größen modellieren - und diese finden Sie überall - nicht nur in der physischen Welt, sondern auch an Orten wie Wirtschaft und Finanzen.
Ich habe Gleitkomma-Mathematik in vielen, vielen Bereichen meiner Programmierkarriere eingesetzt: Chemie, AutoCAD-Arbeiten und sogar das Schreiben eines Monte-Carlo-Simulators, um finanzielle Vorhersagen zu treffen. Tatsächlich gibt es einen Typen namens David E. Shaw, der an der Wall Street auf Fließkommazahlen basierende wissenschaftliche Modellierungstechniken angewendet hat, um Milliarden zu verdienen.
Und natürlich gibt es Computergrafik. Ich berate Sie bei der Entwicklung von Eye Candy für Benutzeroberflächen, und wenn Sie dies heutzutage ohne ein solides Verständnis von Fließkomma, Trigonometrie, Kalkül und linearer Algebra tun, ist dies wie ein Schusswechsel mit einem Taschenmesser.
Warum sollte jemand einen Schwimmer gegenüber einem Doppelgänger brauchen ?
Bei IEEE 754-Standarddarstellungen erhalten Sie mit einem 32-Bit-Float eine Genauigkeit von etwa 7 Dezimalstellen und Exponenten im Bereich von 10 -38 bis 10 38 . Bei einem 64-Bit-Double erhalten Sie eine Genauigkeit von ca. 15 Dezimalstellen und Exponenten im Bereich von 10 -307 bis 10 307 .
Es mag so aussehen, als ob ein Schwimmer genug wäre für das, was irgendjemand vernünftigerweise brauchen würde, aber das ist es nicht. Beispielsweise werden viele reale Größen in mehr als 7 Dezimalstellen gemessen.
Aber subtiler gibt es ein Problem, das umgangssprachlich "Rundungsfehler" genannt wird. Binäre Gleitkommadarstellungen sind nur für Werte gültig, deren gebrochene Teile einen Nenner haben, der eine Potenz von 2 ist, wie 1/2, 1/4, 3/4 usw. Um andere Brüche, wie 1/10, darzustellen, "runden" Sie der Wert zum nächsten binären Bruch, aber es ist ein wenig falsch - das ist der "Rundungsfehler". Wenn Sie dann mit diesen ungenauen Zahlen rechnen, können die Ungenauigkeiten in den Ergebnissen weitaus schlimmer sein als die, mit denen Sie begonnen haben - manchmal multiplizieren sich die Fehlerprozentsätze oder häufen sich sogar exponentiell an.
Je mehr Binärziffern Sie bearbeiten müssen, desto näher ist Ihre abgerundete Binärdarstellung an der Zahl, die Sie darstellen möchten, sodass der Rundungsfehler geringer ist. Wenn Sie dann rechnen, können Sie, wenn Sie mit vielen Ziffern arbeiten müssen, viel mehr Operationen ausführen, bevor sich der kumulative Rundungsfehler dort ansammelt, wo es ein Problem ist.
Tatsächlich sind 64-Bit-Doubles mit ihren 15 Dezimalstellen für viele Anwendungen nicht gut genug. Ich habe 1985 80-Bit-Gleitkommazahlen verwendet, und IEEE definiert jetzt einen 128-Bit-Gleitkommatyp (16 Byte), für den ich mir vorstellen kann, dass er verwendet wird.
quelle
Es ist ein weit verbreitetes Missverständnis, dass Sie überall dort, wo Sie mit Geld zu tun haben, den Wert als Ganzzahl (Cent) speichern sollten. Während es in einigen einfachen Fällen wie dem Onlineshop wahr ist, hilft es nicht viel, wenn Sie etwas Fortgeschritteneres haben.
Nehmen wir ein Beispiel: Ein Entwickler verdient 100.000 US-Dollar pro Jahr. Was ist sein genaues Monatsgehalt? Wenn Sie eine Ganzzahl verwenden, erhalten Sie das Ergebnis $ 8333.33 (¢ 833333), das multipliziert mit 12 $ 99.999,96 ergibt. Hat es geholfen, es als Ganzzahl zu behalten? Nein, das tat es nicht.
Verwenden Banken immer Dezimal- / Ganzzahlwerte? Nun, sie übernehmen den Transaktionsteil. Aber sobald Sie zum Beispiel anfangen, über Investment Banking zu sprechen, mit Ausnahme der Verfolgung der tatsächlichen Transaktionen, ist alles andere Float. Da es sich ausschließlich um Inhouse-Code handelt, wird dieser nicht angezeigt , Sie können jedoch bei QuantLib einen Spitzenwert erzielen , der im Wesentlichen derselbe ist (außer viel sauberer ;-).
Warum Schwimmer verwenden? Weil die Verwendung von Dezimalzahlen überhaupt nicht hilft, wenn Sie Funktionen wie Quadratwurzel, Logarithmen, Potenzen mit nicht ganzzahligen Exponenten usw. verwenden. Und natürlich sind Floats viel schneller als Dezimalzahlen.
quelle
$100,000/12
und einen Wagen benutzt haben. Warum sollte das Ergebnis genau 100.000 US-Dollar betragen? Warum wird der Float (oder die Dezimalzahl) nicht jedes Mal auf- oder abgerundet, wenn jemand bezahlt wird? Ich spreche beim Schreiben eines Schecks (Sie können 1/2 oder 1/3 Cent nicht tun) oder einer direkten Einzahlung (ich nehme an, es hat die gleichen Einschränkungen)Was Sie beschrieben haben, ist eine gute Lösung für Situationen, in denen Sie alle Ein- und Ausgänge steuern .
Im eigentlichen Sinne ist das nicht der Fall. Sie müssen in der Lage sein, mit Systemen umzugehen, die Ihnen ihre Daten in gewissem Maße als echten Wert liefern, und von Ihnen erwarten, dass Sie die Daten im gleichen Format zurückgeben. In solchen Fällen Sie werden diese Probleme auftreten.
Tatsächlich treten diese Probleme auch dann auf, wenn Sie die aufgeführten Tricks verwenden. Bei der Berechnung von 17,5% Steuer auf einen Preis erhalten Sie einen Bruchteil der Cent, unabhängig davon, ob Sie den Wert als Dollar oder Cent speichern. Sie müssen die Rundung richtig stellen, da der Steuermann sehr verärgert ist, wenn Sie ihn nicht genug bezahlen. Die Verwendung der richtigen
money
Typen (unabhängig davon, welche Sprache Sie verwenden) bewahrt Sie vor einer Welt voller Schmerzen.quelle
"Gott schuf die ganzen Zahlen, alles andere ist das Werk des Menschen." - Leopold Kronecker (1886).
Per Definition benötigen Sie keine anderen Arten von Zahlen. Die Vollständigkeit einer Programmiersprache beruht auf den einfachen Beziehungen zwischen den verschiedenen Arten von Zahlen. Wenn Sie mit ganzen Zahlen arbeiten können (a / k / a natürliche Zahlen), können Sie alles tun.
Die Frage ist etwas spekulativ, weil man sie nicht braucht . Vielleicht möchten Sie Orte, an denen es bequem oder optimal oder billiger ist oder so?
quelle
Gleitkomma-Dezimaltypen kapseln in einem Satz die Konvertierung in und von ganzzahligen Werten (das ist alles, was der Computer auf binärer Ebene zu tun weiß; es gibt keinen Dezimalpunkt in binären Werten). Schnittstelle für die Berechnung von Dezimalzahlen verstehen.
Wenn Sie sagen, dass Sie keine Gleitkommazahlen benötigen, weil Sie wissen, wie man Dezimalrechnungen mit Ganzzahlen durchführt, ist das so, als ob Sie wissen, wie man Arithmetik auf lange Sicht macht. Warum sollten Sie also einen Taschenrechner verwenden? Sie kennen das Konzept. Bravo. Das bedeutet nicht, dass Sie dieses Wissen die ganze Zeit ausüben müssen. Es ist oft schneller, billiger und verständlicher für einen Nicht-Binär-Experten, einfach 3,5 + 4,6 = 8,1 zu sagen, anstatt die Sig-Feigen in eine Ganzzahl umzuwandeln.
quelle
Der Hauptvorteil von Gleitkommatypen besteht darin, dass aus Laufzeitsicht zwei oder drei Formate (ich wünsche mir, dass mehr Sprachen als 80-Bit-Formate unterstützt werden) für die schnelle Mehrheit der Berechnungszwecke ausreichen. Wenn Programmiersprachen eine Familie von Festkommatypen problemlos unterstützen könnten, wäre die für ein bestimmtes Leistungsniveau erforderliche Hardwarekomplexität bei Festkommatypen häufig geringer als bei Gleitkommatypen. Leider ist eine solche Unterstützung alles andere als "einfach".
Damit eine Programmiersprache 98% der numerischen Anforderungen von Anwendungen effizient erfüllen kann, müsste sie Dutzende von Typen enthalten und Definitionsoperationen für möglicherweise Hunderte von Kombinationen bereitstellen. Selbst wenn eine Programmiersprache eine wunderbare Festkomma-Unterstützung hätte, müssten einige Anwendungen dennoch eine annähernd konstante relative Genauigkeit über einen ausreichend großen Bereich aufrechterhalten, um Gleitkomma zu erfordern. Da Gleitkomma-Berechnungen auf jeden Fall gelegentlich erforderlich sein werden, erzielen Hardwarehersteller in der Regel bessere Ergebnisse, wenn sie sich auf die Rechenleistung mit zwei oder drei Gleitkommaformaten konzentrieren und wenn der Code diese Formate verwendet, wenn sie recht gut funktionieren "Bang for the Buck" als würde versuchen, das Verhalten der Festkomma-Mathematik zu optimieren.
Festkomma-Mathematik war übrigens bei 8-Bit- und 16-Bit-Prozessoren vorteilhafter als bei 32-Bit-Prozessoren. Auf einem 8-Bit-Prozessor würde ein 40-Bit-Typ in einer Situation, in der 32 Bit nicht ausreichen würden, nur 25% mehr Speicherplatz und 25-50% mehr Zeit als der 32-Bit-Typ kosten und 37,5% benötigen. Weniger Speicherplatz und 37,5-60% weniger Zeit als ein 64-Bit-Typ. Wenn auf einer 32-Bit-Plattform ein 32-Bit-Typ für etwas nicht ausreicht, gibt es oft keinen Grund, weniger als 64 Bit zu verwenden. Wenn ein 48-Bit-Festkommatyp ausreichend wäre, würde ein 64-Bit-"Double" genauso gut funktionieren wie der Festkommatyp.
quelle
Im Allgemeinen sollten Sie sehr vorsichtig mit ihnen umgehen. Es ist eine Herausforderung, den Präzisionsverlust zu verstehen, der sich aus einfachen Berechnungen ergeben kann. Das Mitteln einer solchen Zahlenliste ist beispielsweise eine sehr schlechte Idee:
Der Grund dafür ist, dass Sie bei ausreichend großen Listen grundsätzlich alle Datenpunkte verlieren, wenn diese
ans
groß genug werden (siehe z . B. dies ). Das Problem mit diesem Code ist, dass es für kleine Listen wahrscheinlich nur funktioniert - es ist nur maßstabsgetreu, dass es kaputt geht.Persönlich denke ich, dass Sie sie nur verwenden sollten, wenn: a) die Berechnung wirklich schnell sein muss; b) Sie interessieren sich nicht dafür, dass das Ergebnis wahrscheinlich weit davon entfernt ist (es sei denn, Sie wissen wirklich, was Sie tun).
quelle
Ein Gedanke ist, dass Sie die float- oder double-Darstellung verwenden, wenn Sie mit Werten außerhalb des Integer-Bereichs arbeiten müssen.
Heutige Architekturen haben (ungefähr) einen vorzeichenbehafteten ganzzahligen Bereich von +/- 2.147.483.647 (32 Bit) oder +/- 9.223.372.036.854.775.807 (64 Bit). Unsigned erweitert das um den Faktor 2.
IEEE 754-Floats reichen (ungefähr) von +/- 1,4 × 10 ^ −45 bis 3,4 × 10 ^ 38. Double erweitert diesen Bereich auf +/- 5 × 10−324 ± 2.225 × 10 ^ −308, wobei hier viele Bedingungen und Besonderheiten weggelassen werden.
Der offensichtlichste Grund ist natürlich, dass Sie möglicherweise -0 darstellen müssen ;-)
quelle
Der übliche Grund ist, dass sie schnell sind, da die JVM normalerweise die zugrunde liegende Hardwareunterstützung verwendet (es sei denn, Sie verwenden strictfp).
Unter https://stackoverflow.com/questions/517915/when-to-use-strictfp-keyword-injava erfahren Sie, was strictfp impliziert.
quelle
Deshalb brauchen wir 256-Bit-Betriebssysteme.
Die Plankenlänge (die kleinste Entfernung, die Sie messen können) = 10 ^ -35 m
Das beobachtbare Universum hat einen Querschnitt von 14 Mrd. Parsec = 10 ^ 25 m.
Sie können also alles in Einheiten der Plankenlänge als ganze Zahlen messen, wenn Sie nur 200 Bit Genauigkeit haben.
quelle