Warum speichern Computer Dezimalzahlen nicht als zweite ganze Zahl?


24

Computer haben Probleme beim Speichern von Bruchzahlen, bei denen der Nenner keine Lösung für 2 ^ x ist. Dies liegt daran, dass die erste Stelle nach der Dezimalstelle 1/2, die zweite 1/4 (oder 1 / (2 ^ 1) und 1 / (2 ^ 2)) usw. wert ist.

Warum mit allen möglichen Rundungsfehlern umgehen, wenn der Computer den Dezimalteil der Zahl als eine andere ganze Zahl hätte speichern können (was ist daher richtig?)

Das Einzige, woran ich denken kann, ist das Wiederholen von Dezimalstellen (in Basis 10), aber es hätte eine Kantenlösung dafür geben können (wie wir es derzeit bei Unendlich haben).


8
Sie sollten nachsehen, wie Dezimaltypen im Gegensatz zu Float / Double-Typen gespeichert werden.
Oded

9
Ich weiß nicht, wie das genauer ist. Die erste Stelle nach der Dezimalstelle ist 1/10, die zweite 1/100 usw. Wie ist die Genauigkeit, mit der Sie noch Rundungsprobleme haben (wie stellen Sie 1/3 dar)? Der einzige Unterschied besteht darin, welche Werte genau dargestellt werden können.
Martin York

17
Dezimaler Gleitkommawert (das ist, was Sie als zwei bezeichnen, nur in einer etwas umständlicheren Darstellung) ist nicht ungenauer als binärer Gleitkommawert. Der einzige Unterschied besteht darin, welche Werte nicht dargestellt werden können, und da wir an das Dezimalsystem gewöhnt sind, bemerken wir die Fehler der Dezimalversion nicht. Und nein, keiner kann alle rationalen und irrationalen Zahlen darstellen.

1
Letztendlich läuft es auf Effizienz hinaus. Computer sind binär und die Schaltkreise, die mit dieser binären Darstellung arbeiten, sind weitaus weniger komplex. Die Bedeutung davon mag heute etwas abnehmen, aber es war eine Zeit, in der dies sehr bedeutsam war. Auch jede Darstellung, die Sie wählen, um Ihre Zahl (in einem endlichen Bereich) auf einem Computer zu speichern, weist eine endliche Menge von Werten auf, die dargestellt werden können, und alle weisen bei einigen Eingaben Rundungsfehler auf. Das typische Gleitkommaformat mit Mantisse und Exponent bietet einen weitaus größeren Bereich, als dies mit zwei ganzen Zahlen möglich wäre.
Mr.Mindor

1
Ich würde wärmstens empfehlen, einige der Artikel durchzulesen, auf die in meiner Antwort auf die Frage Was verursacht Gleitkomma-Rundungsfehler? Verwiesen wird . die ich gerade mit Details des letzten Artikels in der referenzierten Serie aktualisiert habe. Schauen Sie sich insbesondere an, warum der Fixpunkt Ihren Fließkomma-Blues nicht heilt .
Mark Booth

Antworten:


35

Es gibt tatsächlich Arten von Zahlen, die das tun.

In der binärcodierten Dezimalarithmetik (BCD-Arithmetik) arbeitet der Computer mit Basis 10. Der Grund, warum Sie darauf stoßen, ist selten, dass Platz verschwendet wird: Jede einzelne Ziffer einer Zahl benötigt mindestens vier Bits, während ein Computer ansonsten bis zu speichern könnte 16 Werte in diesem Raum. (Es kann auch langsamer sein, aber es ist möglich, dass hardwarebeschleunigte BCD-Mathematik funktioniert.) Dies ist in der Tat genau das, was die meisten Taschenrechner tun, weshalb es bestimmte Klassen von Rundungsproblemen gibt, die Sie bei einem Casio für 5 USD, der Ihr Mittagessen auf einem Desktop-Computer zu sich nimmt, niemals bekommen werden.

Der andere Weg, den Sie gehen können, ist die Verwendung rationaler Zahlen, dh eines Zählers und eines Nenners, die als ganze Zahlen gespeichert sind. Dies ist tatsächlich in fast allen Sprachen verfügbar, ist genau und ermöglicht es Ihnen, alles in nativen Binärformaten zu speichern. Das Problem ist, dass Benutzer am Ende des Tages wahrscheinlich keine Brüche wie 463/13 oder sogar 35 und 8/13 sehen möchten. Sie wollen 35.615 sehen ... und in dem Moment, in dem Sie dort ankommen, werden Sie mit allen typischen Problemen konfrontiert. Fügen Sie hinzu, dass dieses Format noch mehr Speicherplatz beansprucht und deutlich langsamer als Gleitkomma-Arithmetik sein kann. Sie werden feststellen, dass standardmäßig kein Computer dieses Format verwendet.

Also: Computer können tun, was Sie wollen, aber es ist langsam und es verschwendet Speicherplatz, sodass sie es nur tun, wenn sie es wirklich müssen. Der Rest der Zeit, die Geschwindigkeit und die Platzersparnis von Gleitkommazahlen sind ein besserer Kompromiss.


Meinen Sie nicht vier Bits (keine Bytes) im BCD-Absatz?

3
Die andere Option ist Festkomma-Arithmetik, wobei eine Ganzzahl einen Dezimalbruch darstellt, wenn eine Zahl - z. B. Speichern von Geldwerten (ohne Berechnungen mit Dezimalstellen oder Prozentsätzen), wobei 1 0,01 USD darstellt.
Mattnz

1
@mattnz: Richtig - Fixpunkte sind ein Sonderfall von Rationals.
Jon Purdy

Genial, wusste nicht, dass Taschenrechner das taten.
SomeKittens

3
Es gibt eine dritte Option. Gleitkomma mit einem Dezimal-Exponenten, wie es in C # decimalimplementiert ist: stackoverflow.com/a/5019178/174335 Es ist kein BCD, da es keine individuelle Darstellung von Dezimalstellen gibt und es kein Festkomma ist.
Joren

38

Es gibt zahlreiche Möglichkeiten, gebrochene Zahlen zu speichern, und jede von ihnen hat Vor- und Nachteile.

Gleitkomma ist mit Abstand das beliebteste Format. Dazu werden ein Vorzeichen, eine Mantisse und ein Exponent zur Basis 2 mit Vorzeichen in ganze Zahlen codiert und in eine Reihe von Bits gepackt. Zum Beispiel könnten Sie eine 32-Bit-Mantisse von 0.5(codiert als 0x88888888) und einen 32-Bit-Exponenten mit Vorzeichen von +3( 0x00000003) haben, der zu 4.0( decodieren würde.0.5 * 2 ^ 3). Gleitkommazahlen sind schnell, weil sie in Hardware implementiert sind und ihre Genauigkeit mit absoluter Größe skaliert wird, dh je kleiner die Zahl, desto besser ist Ihre absolute Genauigkeit, sodass der relative Rundungsfehler mit absoluter Größe konstant bleibt. Floats eignen sich hervorragend für Werte, die aus einem kontinuierlichen Bereich abgetastet werden, z. B. Längen, Schalldruckpegel, Lichtpegel usw., und werden daher häufig in der Audio- und Bildverarbeitung sowie in statistischen Analysen und physikalischen Simulationen verwendet. Ihr größter Nachteil ist, dass sie nicht genau sind, das heißt, sie neigen zu Rundungsfehlern und sie können nicht alle Dezimalbrüche genau darstellen. Alle gängigen Programmiersprachen haben eine Art Gleitkomma.

Fixpunktverwendet ausreichend große ganze Zahlen und reserviert implizit einen Teil ihrer Bits für den Bruchteil. Beispielsweise reserviert eine 24,8-Bit-Festkommazahl 24 Bit für den ganzzahligen Teil (einschließlich Vorzeichen) und 8 Bit für den gebrochenen Teil. Wenn Sie diese Zahl um 8 Bit nach rechts verschieben, erhalten Sie den ganzzahligen Teil. Festkommazahlen waren früher beliebt, als Hardware-Gleitkommazahlen selten oder zumindest viel langsamer waren als ihre ganzzahligen Gegenstücke. Festkommazahlen sind zwar in Bezug auf die Genauigkeit etwas einfacher zu handhaben (wenn auch nur, weil sie einfacher zu überlegen sind), sie sind jedoch in nahezu jeder anderen Hinsicht schlechter als Gleitkommazahlen - sie haben weniger Genauigkeit, einen geringeren Bereich und weil sie zusätzlich sind Operationen sind erforderlich, um Berechnungen für die implizite Verschiebung zu korrigieren. Die Festkomma-Mathematik ist heutzutage oft langsamer als die Gleitkomma-Mathematik.

Dezimaltypen funktionieren ähnlich wie Gleitkommazahlen oder Festkommazahlen, setzen jedoch ein Dezimalsystem voraus, dh ihr Exponent (implizit oder explizit) codiert die Potenz 10 und nicht die Potenz 2. Eine Dezimalzahl könnte zum Beispiel eine Mantisse von 23456und einen Exponenten von codieren -2, und dies würde sich erweitern auf234.56. Dezimalzahlen sind langsamer als Gleitkommazahlen, da die Arithmetik nicht fest in der CPU verankert ist. Sie eignen sich jedoch ideal für alle Fälle, in denen Dezimalzahlen erforderlich sind und bei denen diese Zahlen genau sein müssen. Anzeigetafeln usw. In einigen Programmiersprachen sind Dezimaltypen integriert (z. B. C #), in anderen sind Bibliotheken erforderlich, um sie zu implementieren. Beachten Sie, dass Dezimalzahlen zwar nicht wiederholende Dezimalbrüche genau darstellen können, ihre Genauigkeit jedoch nicht besser ist als die von Gleitkommazahlen. Wenn Sie Dezimalzahlen auswählen, erhalten Sie lediglich exakte Darstellungen von Zahlen, die in einem Dezimalsystem exakt dargestellt werden können (genau wie Floats binäre Brüche exakt darstellen können).

Rationale Zahlen speichern einen Zähler und einen Denumerator, wobei normalerweise ein ganzzahliger Bignum-Typ verwendet wird (ein numerischer Typ, der so groß werden kann, wie es die Speicherbeschränkungen des Computers zulassen). Dies ist der einzige Datentyp aus dem Bündel, der Zahlen wie 1/3oder genau modellieren kann 3/17, und Operationen an ihnen führen im Gegensatz zu den anderen Datentypen zu korrekten Ergebnissen für Dinge wie3 * 1/3. Die Mathematik ist ziemlich einfach, obwohl es ziemlich schwierig ist, einen effizienten Faktorisierungsalgorithmus zu entwickeln. In einigen Programmiersprachen sind rationale Typen integriert (z. B. Common Lisp). Zu den Nachteilen von rationalen Methoden gehört, dass sie langsam sind (viele Operationen erfordern das Reduzieren von Brüchen und das Faktorisieren ihrer Komponenten), und dass viele allgemeine Operationen schwer oder unmöglich zu implementieren sind. Die meisten Implementierungen führen dazu, dass das Rationale in einen Schwebezustand übergeht, wenn dies geschieht (z. B. wenn Sie einen Aufruf tätigen) sin()auf einem rationalen).

BCD (Binary Coded Decimal) verwendet "Nibbles" (Gruppen von 4 Bits), um einzelne Ziffern zu codieren. Da ein Nibble 16 verschiedene Werte enthalten kann, Dezimalzahlen jedoch nur 10 erfordern, gibt es 6 "unzulässige" Werte pro Nibble. Wie Dezimalzahlen sind auch BCD-Zahlen dezimalgenau, dh, Berechnungen mit Dezimalzahlen funktionieren genauso wie mit Stift und Papier. Arithmetische Regeln für BCD sind etwas umständlich, aber der Vorteil ist, dass das Konvertieren in Zeichenfolgen einfacher ist als bei einigen anderen Formaten, was besonders für ressourcenarme Umgebungen wie eingebettete Systeme interessant ist.

Zeichenfolgen , ja, einfache alte Zeichenfolgen, können auch zur Darstellung von Bruchzahlen verwendet werden. Technisch ist dies BCD sehr ähnlich, nur dass es einen expliziten Dezimalpunkt gibt und Sie ein vollständiges Byte pro Dezimalstelle verwenden. Daher ist das Format verschwenderisch (nur 11 von 256 möglichen Werten werden verwendet), aber es ist einfacher zu analysieren und zu generieren als BCD. Da alle verwendeten Werte "unauffällig", harmlos und plattformneutral sind, können Zeichenfolgen-codierte Zahlen problemlos über Netzwerke übertragen werden. Es ist ungewöhnlich, dass das Rechnen direkt mit Zeichenfolgen ausgeführt wird, aber es ist möglich, und wenn Sie dies tun, sind sie genauso dezimalgenau wie die anderen Dezimalformate (Dezimalzahlen und BCD).


Sicherlich hat 32-Bit-Festkomma eine höhere Genauigkeit als 32-Bit-Gleitkomma, da Festkommadarstellungen keine Mantisse enthalten.
Han

4
@han: Hängt von der Größe der Nummer ab, die Sie speichern möchten. Schwimmer geben Ihnen (ungefähr) die gleiche Präzision, egal wie groß oder klein die Zahl ist, während Festpunkt Ihnen nur dann die volle Präzision gibt, wenn die Zahl, die Sie speichern möchten, perfekt in den Bereich passt.
Leo

@han Nicht unbedingt, beide können immer noch 2 ^ 32 verschiedene Werte darstellen. Die Menge der mitgeführten Informationen ist unabhängig von der Darstellung identisch. Reichweite und Präzision gehen jedoch Hand in Hand, sodass die Festkomma-Arithmetik in bestimmten Bereichen genauer sein kann. Und vermeidet unangenehme Rundungsprobleme, wenn Sie die Grenzen kennen, innerhalb derer Sie arbeiten können.
zxcdw

@han: Sie haben die gleiche Präzision (oder fast). Der Unterschied besteht darin, dass bei Festkommazahlen die Genauigkeit (wie in der Größe eines diskreten Schritts von einer Zahl zu ihrem Nachfolger) wie bei ganzen Zahlen konstant ist, während sie bei Floats ungefähr linear mit dem absoluten Wert wächst - dem Float Nummer 1.0 hat mehr Präzision als die Nummer 10.000.000.0 (eine Million Mal mehr, ungefähr).
tdammers

6

Gleitkommazahlen stellen einen großen Wertebereich dar. Dies ist sehr nützlich, wenn Sie die Werte nicht im Voraus kennen, aber einen Kompromiss eingehen. Die Darstellung von 1/10 ^ 100 mit einer zweiten Ganzzahl würde nicht funktionieren.

Einige Sprachen (und einige Bibliotheken) haben andere Eigenschaften. Lisp hat traditionell unendlich genaue ganze Zahlen. Cobol hat Berechnungen mit Festkomma-Dezimalzahlen.

Sie müssen die der Problemdomäne entsprechende Zahlendarstellung auswählen.


1

Es hört sich so an, als würden Sie Festkommazahlen beschreiben .

Denken Sie daran, dass das Speichern des Bruchteils einer Zahl an einem separaten Ort genau mit dem Erstellen eines einzelnen, doppelt so langen Raums und dem Speichern des gesamten und des Bruchteils in den beiden separaten Hälften identisch ist. Mit anderen Worten, es ist identisch mit dem Speichern der Zahl als Ganzzahl, setzt jedoch einfach eine feste Anzahl von Dezimalstellen voraus.

Normalerweise werden Gleitkommazahlen mit einer binären Variation der wissenschaftlichen Notation gespeichert, da es normalerweise auf signifikante Ziffern ankommt. Es gibt jedoch viele andere Methoden. Festkomma-Dezimalzahlen werden üblicherweise zum Speichern von Währungswerten verwendet, bei denen die Genauigkeit bis zu einer bestimmten ganzen Anzahl von Dezimalstellen kritisch ist, sich die Anzahl der erforderlichen Dezimalstellen jedoch nie ändert.


1

Das würde BCD heißen, ich denke, Sie können es immer noch verwenden, wenn Sie wirklich wollen. Es lohnt sich jedoch nicht wirklich als:

  1. Bei 64-Bit-Gleitkommazahlen kommt es sehr selten zu Rundungsfehlern
  2. Das macht das Rechnen komplex und ineffizient
  3. Alle 4 Bits werden 6 Werte verschwendet

BCD-Mathematik wurde häufig in frühen 8-Bit-Mikroprozessorsystemen verwendet. Auf einem gängigen Mikroprozessor (dem 6502) sind Addition und Subtraktion mit BCD pro Byte genauso schnell wie mit Binär. Videospiele verwendeten häufig die BCD-Mathematik für die Ergebniserfassung. Es gibt keine spezielle Behandlung für das Einwickeln von Punktzahlen bei 1.000.000 Punkten. Wenn Sie stattdessen 1 zu "99 99 99" addieren, erhalten Sie "00 00 00" mit einem Übertrag, der ignoriert wird. Der zusätzliche Aufwand für das Hinzufügen von Scores bei BCD ist im Vergleich zu den Kosten für die Konvertierung eines Binärwerts in ein anzeigbares Format gering.
Supercat

1

Die kurze Antwort ist, dass Fließkommazahlen für wissenschaftliche Berechnungen entwickelt wurden. Es kann eine Zahl mit (bis zu) einer bestimmten Anzahl von signifikanten Stellen speichern, was genau der Genauigkeit entspricht, die in den meisten wissenschaftlichen Berechnungen gemessen wird.

Dies wird in der Hardware in der Regel unterstützt, da wissenschaftliche Berechnungen am meisten von der Hardware-Unterstützung profitierten. Zum Beispiel werden Finanzberechnungen häufig mit anderen Formaten durchgeführt. Finanzsoftware führt jedoch in der Regel nur wenig echte Berechnungen durch, sodass die Leistung für die meisten Finanzsoftwareprodukte vollkommen ausreicht, obwohl die erforderlichen Formate nur in Software unterstützt werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.