In SO wurden mehrere Fragen zur Gleitkomma-Darstellung gestellt. Zum Beispiel hat die Dezimalzahl 0.1 keine exakte Binärdarstellung, daher ist es gefährlich, den Operator == zu verwenden, um sie mit einer anderen Gleitkommazahl zu vergleichen. Ich verstehe die Prinzipien hinter der Gleitkomma-Darstellung.
Was ich nicht verstehe, ist, warum aus mathematischer Sicht die Zahlen rechts vom Dezimalpunkt "spezieller" sind als die links?
Zum Beispiel hat die Zahl 61.0 eine genaue binäre Darstellung, da der integrale Teil einer beliebigen Zahl immer genau ist. Die Zahl 6.10 ist jedoch nicht genau. Ich habe nur die Dezimalstelle um eine Stelle verschoben und bin plötzlich von Exactopia nach Inexactville gegangen. Mathematisch sollte es keinen intrinsischen Unterschied zwischen den beiden Zahlen geben - es sind nur Zahlen.
Wenn ich dagegen die Dezimalstelle um eine Stelle in die andere Richtung bewege, um die Zahl 610 zu erhalten, bin ich immer noch in Exactopia. Ich kann weiter in diese Richtung gehen (6100, 610000000, 610000000000000) und sie sind immer noch genau, genau, genau. Sobald die Dezimalstelle einen bestimmten Schwellenwert überschreitet, sind die Zahlen nicht mehr genau.
Was ist los?
Bearbeiten: Um dies zu verdeutlichen, möchte ich mich von Diskussionen über branchenübliche Darstellungen wie IEEE fernhalten und mich an das halten, was ich für den mathematisch "reinen" Weg halte. In Basis 10 sind die Positionswerte:
... 1000 100 10 1 1/10 1/100 ...
In binärer Form wären sie:
... 8 4 2 1 1/2 1/4 1/8 ...
Es gibt auch keine willkürlichen Grenzen für diese Zahlen. Die Positionen erhöhen sich auf unbestimmte Zeit nach links und rechts.
quelle
Antworten:
Dezimalzahlen können genau dargestellt werden, wenn Sie genügend Platz haben - nur nicht von schwebenden binären Kommazahlen. Wenn Sie einen Gleitkomma- Dezimalpunkttyp verwenden (z. B.
System.Decimal
in .NET), können viele Werte, die nicht genau im binären Gleitkomma dargestellt werden können, genau dargestellt werden.Betrachten wir es anders - in Basis 10, mit der Sie wahrscheinlich vertraut sind, können Sie 1/3 nicht genau ausdrücken. Es ist 0,3333333 ... (wiederkehrend). Der Grund, warum Sie 0.1 nicht als binäre Gleitkommazahl darstellen können, ist genau der gleiche Grund. Sie können 3, 9 und 27 genau darstellen - aber nicht 1/3, 1/9 oder 1/27.
Das Problem ist, dass 3 eine Primzahl ist, die kein Faktor 10 ist. Dies ist kein Problem, wenn Sie eine Zahl mit 3 multiplizieren möchten : Sie können immer mit einer Ganzzahl multiplizieren, ohne auf Probleme zu stoßen. Aber wenn Sie teilen durch eine Zahl , die eine Primzahl ist und kein Faktor Ihrer Basis können Sie in Schwierigkeiten geraten (und wird dies tun , wenn Sie zu teilen versuchen 1 von dieser Zahl).
Obwohl 0,1 normalerweise als einfachstes Beispiel für eine exakte Dezimalzahl verwendet wird, die nicht genau im binären Gleitkomma dargestellt werden kann, ist 0,2 wohl ein einfacheres Beispiel, da es 1/5 ist - und 5 die Primzahl ist, die Probleme zwischen Dezimalzahl und Binärzahl verursacht .
Randnotiz zum Problem der endlichen Repräsentation:
Einige Gleitkomma-Dezimalpunkttypen haben eine feste Größe,
System.Decimal
anderejava.math.BigDecimal
sind "beliebig groß" - aber sie stoßen irgendwann an eine Grenze, unabhängig davon, ob es sich um Systemspeicher oder die theoretische maximale Größe eines Arrays handelt. Dies ist jedoch ein völlig anderer Punkt als der Hauptpunkt dieser Antwort. Selbst wenn Sie eine wirklich willkürlich große Anzahl von Bits zum Spielen hätten, könnten Sie die Dezimalzahl 0,1 in einer Gleitkomma-Binärpunktdarstellung nicht genau darstellen. Vergleichen Sie das mit der umgekehrt: Da eine beliebige Anzahl von Dezimalstellen, Sie können genau eine beliebige Anzahl darstellen , die als schwimmende binäre Punkt genau darstellbar ist.quelle
1
und die Dezimaldarstellung dargestellten Zahlen0.9...
(unendlich wiederholtes9
s nach dem Dezimalpunkt) sind gleich. Der vielleicht einfachste Weg, dies zu sehen, ist der folgende: Sei x =0.9...
. Beachten Sie das10x = 9.9....
. Deshalb9x = 10x - x = 9.9... - 0.9... = 9
damit9x = 9
undx = 1
. Es gibt andere Möglichkeiten, dies zu sehen, aber ich glaube, dass dies die einfachste ist.Lassen Sie uns für einen Moment von den Einzelheiten der Basen 10 und 2 Abstand nehmen. Fragen wir in der Basis
b
, welche Zahlen terminierende Darstellungen haben und welche nicht? Ein Moment des Gedanke sagt uns , dass eine Zahl mitx
einem Abschluss hatb
-Darstellung , wenn und nur wenn es eine ganze Zahl vorhanden ,n
so dassx b^n
eine ganze Zahl ist.So hat zum Beispiel
x = 11/500
eine abschließende 10-Darstellung, weil wirn = 3
und dannx b^n = 22
eine ganze Zahl auswählen können . Dies istx = 1/3
jedoch nicht der Fall, dan
wir die 3 nicht loswerden können , was auch immer wir auswählen.Dieses zweite Beispiel veranlasst uns, über Faktoren nachzudenken, und wir können sehen, dass wir für jedes Rationale
x = p/q
(das in niedrigsten Begriffen angenommen wird) die Frage beantworten können, indem wir die Primfaktoren vonb
und vergleichenq
. Wennq
Primfaktoren nicht in der Primfaktorisierung von enthalten sindb
, werden wir niemals einen geeigneten finden können, umn
diese Faktoren loszuwerden.So für die Basis 10, eine beliebige
p/q
, woq
Primfaktoren andere als 2 oder 5 hat keinen Abschluss Darstellung haben.p/q
Wenn wir nun zu den Basen 10 und 2 zurückkehren, sehen wir, dass jedes Rationale mit einer abschließenden 10-Darstellung genau dann die Form hat , wennq
nur2
s und5
s in seiner Primfaktorisierung enthalten sind. und dieselbe Zahl wird genau dann eine abschließende 2-Darstellung haben, wennq
nur2
s in ihrer Primfaktorisierung enthalten ist.Aber einer dieser Fälle ist eine Teilmenge des anderen! Wann immer
es ist offensichtlich auch wahr, dass
oder anders ausgedrückt, wenn
p/q
eine terminierende 2-Darstellungp/q
eine terminierende 10-Darstellung hat . Das Umgekehrte gilt jedoch nicht - wennq
eine Primfaktorisierung eine 5 enthält, hat sie eine abschließende 10-Darstellung, aber keine abschließende 2-Darstellung. Dies ist das0.1
Beispiel, das in anderen Antworten erwähnt wird.Da haben wir also die Antwort auf Ihre Frage - da die Primfaktoren von 2 eine Teilmenge der Primfaktoren von 10 sind, sind alle 2-terminierenden Zahlen 10-terminierende Zahlen, aber nicht umgekehrt. Es geht nicht um 61 gegen 6.1 - es geht um 10 gegen 2.
Zum Schluss: Wenn einige Leute die Basis 17 verwenden (sagen wir), aber unsere Computer die Basis 5 verwenden, wäre Ihre Intuition dadurch niemals in die Irre geführt worden - es gäbe keine (nicht null, nicht ganzzahligen) Zahlen, die endeten in beiden Fällen!
quelle
0.15
tatsächlich (wenn als IEEE-Double gespeichert) "0.149999999999999994448884876874". Siehe jsfiddle .Der (mathematische) Grund ist, dass wenn Sie mit ganzen Zahlen arbeiten, diese zählbar unendlich sind .
Das heißt, obwohl es unendlich viele davon gibt, können wir alle Elemente in der Sequenz "zählen", ohne sie zu überspringen. Das heißt, wenn wir das Element an die
610000000000000
dritte Position in der Liste bringen möchten , können wir es über eine Formel herausfinden.Reelle Zahlen sind jedoch unzählig unendlich . Sie können nicht sagen "Geben Sie mir die reale Nummer an Position
610000000000000
" und erhalten Sie eine Antwort zurück. Der Grund dafür ist, dass es auch zwischen0
und1
unendlich viele Werte gibt, wenn Sie Gleitkommawerte berücksichtigen. Gleiches gilt für zwei beliebige Gleitkommazahlen.Mehr Info:
http://en.wikipedia.org/wiki/Countable_set
http://en.wikipedia.org/wiki/Uncountable_set
Update: Ich entschuldige mich, ich habe die Frage anscheinend falsch interpretiert. In meiner Antwort geht es darum, warum wir nicht jeden realen Wert darstellen können. Ich hatte nicht bemerkt, dass Gleitkomma automatisch als rational klassifiziert wurde.
quelle
Um zu wiederholen, was ich in meinem Kommentar zu Herrn Skeet gesagt habe: Wir können 1/3, 1/9, 1/27 oder jede rationale Dezimalschreibweise darstellen. Dazu fügen wir ein zusätzliches Symbol hinzu. Zum Beispiel eine Zeile über den Ziffern, die sich in der Dezimalerweiterung der Zahl wiederholen. Was wir brauchen, um Dezimalzahlen als Folge von Binärzahlen darzustellen, sind 1) eine Folge von Binärzahlen, 2) ein Radixpunkt und 3) ein anderes Symbol, um den sich wiederholenden Teil der Folge anzuzeigen.
Hehners Zitatnotation ist ein Weg, dies zu tun. Er verwendet ein Anführungszeichen, um den sich wiederholenden Teil der Sequenz darzustellen. Der Artikel: http://www.cs.toronto.edu/~hehner/ratno.pdf und der Wikipedia-Eintrag: http://en.wikipedia.org/wiki/Quote_notation .
Es gibt nichts, was besagt, dass wir unserem Repräsentationssystem kein Symbol hinzufügen können, sodass wir Dezimalrationen genau in binärer Anführungszeichen darstellen können und umgekehrt.
quelle
BCD - Binärcodierte Dezimalzahl - Darstellungen sind genau. Sie sind nicht sehr platzsparend, aber das ist ein Kompromiss, den Sie in diesem Fall für die Genauigkeit eingehen müssen.
quelle
Es ist der gleiche Grund, warum Sie 1/3 nicht genau in Basis 10 darstellen können, Sie müssen 0,33333 (3) sagen. In der Binärdatei handelt es sich um dieselbe Art von Problem, das jedoch nur bei unterschiedlichen Zahlen auftritt.
quelle
(Hinweis: Ich werde 'b' anhängen, um hier Binärzahlen anzugeben. Alle anderen Zahlen werden dezimal angegeben.)
Eine Möglichkeit, über Dinge nachzudenken, ist die wissenschaftliche Notation. Wir sind es gewohnt, Zahlen in wissenschaftlicher Notation wie 6.022141 * 10 ^ 23 zu sehen. Gleitkommazahlen werden intern in einem ähnlichen Format gespeichert - Mantisse und Exponent, jedoch mit Zweierpotenzen anstelle von zehn.
Ihre 61.0 könnte mit der Mantisse und den Exponenten als 1.90625 * 2 ^ 5 oder 1.11101b * 2 ^ 101b umgeschrieben werden. Um dies mit zehn zu multiplizieren und (den Dezimalpunkt zu verschieben), können wir Folgendes tun:
(1,90625 * 2 ^ 5) * (1,25 * 2 ^ 3) = (2,3828125 * 2 ^ 8) = (1,19140625 * 2 ^ 9)
oder in mit der Mantisse und Exponenten in binär:
(1.11101b * 2 ^ 101b) * (1.01b * 2 ^ 11b) = (10.0110001b * 2 ^ 1000b) = (1.00110001b * 2 ^ 1001b)
Beachten Sie, was wir dort getan haben, um die Zahlen zu multiplizieren. Wir haben die Mantissen multipliziert und die Exponenten hinzugefügt. Da die Mantisse größer als zwei endete, normalisierten wir das Ergebnis durch Anstoßen des Exponenten. Es ist genau so, als würden wir den Exponenten anpassen, nachdem wir eine Operation mit Zahlen in dezimaler wissenschaftlicher Notation durchgeführt haben. In jedem Fall hatten die Werte, mit denen wir gearbeitet haben, eine endliche Darstellung in Binärform, und so erzeugten die Werte, die durch die grundlegenden Multiplikations- und Additionsoperationen ausgegeben wurden, auch Werte mit einer endlichen Darstellung.
Überlegen Sie nun, wie wir 61 durch 10 teilen würden. Wir beginnen mit der Teilung der Mantissen 1.90625 und 1.25. In Dezimalzahlen ergibt dies 1,525, eine schöne kurze Zahl. Aber was ist das, wenn wir es in eine Binärdatei konvertieren? Wir machen das auf die übliche Weise - subtrahieren die größte Zweierpotenz, wann immer dies möglich ist, genau wie das Konvertieren von ganzzahligen Dezimalstellen in Binärzahlen, aber wir verwenden negative Zweierpotenzen:
Oh oh. Jetzt sind wir in Schwierigkeiten. Es stellt sich heraus, dass 1,90625 / 1,25 = 1,525 ein sich wiederholender Bruch ist, wenn er in Binärform ausgedrückt wird: 1,11101b / 1,01b = 1,10000110011 ... b Unsere Maschinen haben nur so viele Bits, um diese Mantisse zu halten, und runden den Bruch nur ab und nehme Nullen über einen bestimmten Punkt hinaus an. Der Fehler, den Sie sehen, wenn Sie 61 durch 10 teilen, ist der Unterschied zwischen:
1.100001100110011001100110011001100110011 ... b * 2 ^ 10b
und sagen wir:
1.100001100110011001100110b * 2 ^ 10b
Es ist diese Rundung der Mantisse, die zu einem Genauigkeitsverlust führt, den wir mit Gleitkommawerten assoziieren. Selbst wenn die Mantisse genau ausgedrückt werden kann (z. B. wenn nur zwei Zahlen addiert werden), können wir dennoch einen numerischen Verlust erhalten, wenn die Mantisse nach dem Normalisieren des Exponenten zu viele Ziffern benötigt, um zu passen.
Wir machen so etwas tatsächlich die ganze Zeit, wenn wir Dezimalzahlen auf eine überschaubare Größe runden und nur die ersten paar Ziffern davon angeben. Da wir das Ergebnis dezimal ausdrücken, fühlt es sich natürlich an. Wenn wir jedoch eine Dezimalstelle runden und sie dann in eine andere Basis konvertieren, sieht sie genauso hässlich aus wie die Dezimalstellen, die wir aufgrund der Gleitkomma-Rundung erhalten.
quelle
Das ist eine gute Frage.
Alle Ihre Fragen basieren auf "Wie repräsentieren wir eine Zahl?"
ALLE Zahlen können mit Dezimaldarstellung oder mit binärer Darstellung (Zweierkomplement) dargestellt werden. Alle von ihnen !!
ABER einige (die meisten von ihnen) erfordern eine unendliche Anzahl von Elementen ("0" oder "1" für die Binärposition oder "0", "1" bis "9" für die Dezimaldarstellung).
Wie 1/3 in Dezimaldarstellung (1/3 = 0,3333333 ... <- mit einer unendlichen Zahl von "3")
Wie 0,1 in binär (0,1 = 0,00011001100110011 .... <- mit einer unendlichen Zahl von "0011")
Alles ist in diesem Konzept. Da Ihr Computer nur endliche Ziffern (dezimal oder binär) berücksichtigen kann , können nur einige Zahlen in Ihrem Computer genau dargestellt werden ...
Und wie gesagt, Jon, 3 ist eine Primzahl, die kein Faktor 10 ist, so dass 1/3 nicht mit einer endlichen Anzahl von Elementen in Basis 10 dargestellt werden kann.
Selbst mit Arithmetik mit beliebiger Genauigkeit kann das Nummerierungspositionssystem in Basis 2 6.1 nicht vollständig beschreiben, obwohl es 61 darstellen kann.
Für 6.1 müssen wir eine andere Darstellung verwenden (wie die Dezimaldarstellung oder IEEE 854, die Basis 2 oder Basis 10 für die Darstellung von Gleitkommawerten zulässt).
quelle
Wenn Sie mit Gleitkommazahlen eine ausreichend große Zahl erstellen (wie dies bei Exponenten der Fall ist), werden Sie auch vor dem Dezimalpunkt ungenau. Ich glaube also nicht, dass Ihre Frage völlig gültig ist, weil die Prämisse falsch ist. Es ist nicht so, dass eine Verschiebung um 10 immer zu mehr Präzision führt, da die Gleitkommazahl irgendwann Exponenten verwenden muss, um die Größe der Zahl darzustellen, und auf diese Weise auch an Präzision verliert.
quelle
Ich bin überrascht, dass dies noch niemand gesagt hat: Verwenden Sie fortgesetzte Brüche . Jede rationale Zahl kann auf diese Weise endlich binär dargestellt werden.
Einige Beispiele:
1/3 (0,3333 ...)
5/9 (0,5555 ...)
10/43 (0,232558139534883720930 ...)
9093/18478 (0.49209871198181621387596060179673 ...)
Von hier aus gibt es eine Vielzahl bekannter Möglichkeiten, eine Folge von ganzen Zahlen im Speicher zu speichern.
Neben der präzisen Speicherung Ihrer Zahl bieten fortgesetzte Brüche auch einige andere Vorteile, z. B. die beste rationale Approximation. Wenn Sie sich entscheiden, die Zahlenfolge in einem fortgesetzten Bruch vorzeitig zu beenden, erhalten Sie mit den verbleibenden Ziffern (wenn sie zu einem Bruch rekombiniert werden) den bestmöglichen Bruch. So werden Annäherungen an pi gefunden:
Pis fortgesetzte Fraktion:
Wenn Sie die Sequenz bei 1 beenden, erhalten Sie den Bruch:
355/113
Das ist eine ausgezeichnete rationale Annäherung.
quelle
In der Gleichung
Daher habe ich mich nur gefragt, ob wir ein logarithmisches Basissystem für binäre wie haben könnten,
Das könnte das Problem möglicherweise lösen. Wenn Sie also etwas wie 32.41 in Binärform schreiben möchten, wäre dies der Fall
Oder
quelle
Das Problem ist, dass Sie nicht wirklich wissen, ob die Zahl tatsächlich genau 61,0 ist. Bedenken Sie:
Was ist der Wert von c? Es ist nicht genau 61, weil b nicht wirklich .1 ist, weil .1 keine exakte binäre Darstellung hat.
quelle
Es gibt einen Schwellenwert, da die Bedeutung der Ziffer von einer Ganzzahl zu einer Nicht-Ganzzahl gewechselt ist. Um 61 darzustellen, haben Sie 6 * 10 ^ 1 + 1 * 10 ^ 0; 10 ^ 1 und 10 ^ 0 sind beide ganze Zahlen. 6.1 ist 6 * 10 ^ 0 + 1 * 10 ^ -1, aber 10 ^ -1 ist 1/10, was definitiv keine ganze Zahl ist. So landen Sie in Inexactville.
quelle
Eine Parallele kann aus Brüchen und ganzen Zahlen bestehen. Einige Brüche, z. B. 1/7, können ohne viele, viele Dezimalstellen nicht in Dezimalform dargestellt werden. Da Gleitkomma binär ist, ändern sich die Sonderfälle, es treten jedoch die gleichen Genauigkeitsprobleme auf.
quelle
Es gibt unendlich viele rationale Zahlen und eine endliche Anzahl von Bits, mit denen sie dargestellt werden können. Siehe http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems .
quelle
Die Zahl 61.0 hat zwar eine exakte Gleitkommaoperation - dies gilt jedoch nicht für alle Ganzzahlen. Wenn Sie eine Schleife geschrieben haben, die sowohl einer Gleitkommazahl mit doppelter Genauigkeit als auch einer 64-Bit-Ganzzahl eine hinzufügt, erreichen Sie schließlich einen Punkt, an dem die 64-Bit-Ganzzahl eine Zahl perfekt darstellt, der Gleitkomma jedoch nicht. weil es nicht genug signifikante Bits gibt.
Es ist nur viel einfacher, den Approximationspunkt auf der rechten Seite des Dezimalpunkts zu erreichen. Wenn Sie anfangen würden, alle Zahlen in binären Gleitkommazahlen zu schreiben, wäre dies sinnvoller.
Eine andere Art, darüber nachzudenken, ist, dass Sie eine Multiplikation mit Zehnerpotenzen (10 ^ 1, 10 ^ -1) durchführen, wenn Sie feststellen, dass 61.0 in Basis 10 perfekt darstellbar ist und das Verschieben des Dezimalpunkts dies nicht ändert ). Beim Gleitkomma wirkt sich das Multiplizieren mit Zweierpotenzen nicht auf die Genauigkeit der Zahl aus. Nehmen Sie 61.0 und teilen Sie es wiederholt durch drei, um zu veranschaulichen, wie eine perfekt genaue Zahl ihre genaue Darstellung verlieren kann.
quelle
Sie kennen ganzzahlige Zahlen, oder? Jedes Bit repräsentiert 2 ^ n
2 ^ 4 = 16
2 ^ 3 = 8
2 ^ 2 = 4
2 ^ 1 = 2
2 ^ 0 = 1
Nun, es ist dasselbe für Gleitkomma (mit einigen Unterscheidungen), aber die Bits repräsentieren 2 ^ -n 2 ^ -1 = 1/2 = 0,5
2 ^ -2 = 1 / (2 * 2) = 0,25
2 ^ -3 = 0,125
2 ^ -4 = 0,0625
Gleitkomma-Binärdarstellung:
Vorzeichen Exponentenbruch (ich denke, unsichtbar 1 wird an den Bruch angehängt)
B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0
quelle
Die Antwort mit der höchsten Punktzahl hat es geschafft.
Zuerst haben Sie Basis 2 und Basis 10 in Ihrer Frage gemischt. Wenn Sie dann eine Zahl auf die rechte Seite setzen, die nicht in die Basis teilbar ist, treten Probleme auf. Wie 1/3 in Dezimalzahl, weil 3 nicht in eine Potenz von 10 oder 1/5 in Binärform geht, was nicht in eine Potenz von 2 geht.
Ein weiterer Kommentar, obwohl NIEMALS gleich mit Gleitkommazahlen, Punkt. Selbst wenn es sich um eine exakte Darstellung handelt, gibt es in einigen Gleitkommasystemen einige Zahlen, die auf mehr als eine Weise genau dargestellt werden können (IEEE ist diesbezüglich schlecht, es ist zunächst eine schreckliche Gleitkommaspezifikation, also erwarten Sie Kopfschmerzen). Kein Unterschied hier 1/3 ist nicht gleich der Zahl auf Ihrem Rechner 0.3333333, egal wie viele 3en rechts vom Dezimalpunkt stehen. Es ist oder kann nah genug sein, ist aber nicht gleich. Sie würden also erwarten, dass so etwas wie 2 * 1/3 je nach Rundung nicht 2/3 entspricht. Verwenden Sie niemals gleich mit Gleitkomma.
quelle
Wie wir bereits besprochen haben, kann in der Gleitkomma-Arithmetik die Dezimalzahl 0,1 nicht perfekt binär dargestellt werden.
Gleitkomma- und Ganzzahldarstellungen liefern Gitter oder Gitter für die dargestellten Zahlen. Wenn die Arithmetik durchgeführt wird, fallen die Ergebnisse vom Gitter ab und müssen durch Runden auf das Gitter zurückgesetzt werden. Beispiel ist 1/10 in einem binären Gitter.
Wenn wir eine binär codierte Dezimaldarstellung verwenden, wie es ein Gentleman vorgeschlagen hat, könnten wir dann Zahlen im Raster behalten?
quelle