Wie viele signifikante Ziffern haben Floats und Doubles in Java?

81

Hat ein Float 32 Binärziffern und ein Doppel 64 Binärziffern? Die Dokumentation war zu schwer zu verstehen.

Werden alle Bits in signifikante Ziffern übersetzt? Oder nimmt die Position des Dezimalpunkts einige der Bits ein?

Eamon Moloney
quelle
2
Werden all diese Bits in signifikante Ziffern übersetzt? Oder nimmt die Position des Dezimalpunkts einige der Bits ein?
Eamon Moloney
@ user1774214 Gleitkommazahlen werden überhaupt nicht wie Ganzzahlen codiert. Schauen Sie sich den Link an, den ich gebe. Sie müssen zum Beispiel verstehen, dass die Präzision nicht einheitlich ist.
Denys Séguret
@dystroy Ich bin mir nicht sicher, was du mit "die Präzision ist nicht einheitlich" meinst. Es ist ziemlich gleichmäßig 53 und 24 Bit Genauigkeit, es sei denn, Sie beziehen sich auf Denormale.
Pascal Cuoq
2
@PascalCuoq gibt es mehr Präzision für kleinere Zahlen. Wenn sich der Exponent ändert (oder der Punkt schwebt), repräsentiert die Mantisse immer die gleiche Anzahl von Ziffern. Wenn also die Zahl groß ist, kann die Mantisse niedrigere signifikante Stellen nicht so stark "erreichen", was zu einer geringeren Genauigkeit führt.
Vituel
3
@Virtuel Die Genauigkeit beträgt 53 Bit. Das nennen wir Präzision. Sie scheinen an die absolute Genauigkeit zu denken oder so.
Pascal Cuoq

Antworten:

105

float : 32 Bit (4 Byte), wobei 23 Bit für die Mantisse verwendet werden (ca. 7 Dezimalstellen). Für den Exponenten werden 8 Bits verwendet, sodass ein Gleitkomma den Dezimalpunkt mit diesen 8 Bits nach rechts oder links „verschieben“ kann. Auf diese Weise wird vermieden, dass viele Nullen in der Mantisse wie in 0,0000003 (3 × 10 -7 ) oder 3000000 (3 × 10 7 ) gespeichert werden . Es wird 1 Bit als Vorzeichenbit verwendet.

double : 64 Bit (8 Byte), wobei 52 Bit für die Mantisse verwendet werden (ca. 16 Dezimalstellen). Für den Exponenten werden 11 Bits verwendet, und 1 Bit ist das Vorzeichenbit.

Da wir binär verwenden (nur 0 und 1), ist ein Bit in der Mantisse implizit 1 (sowohl float als auch double verwenden diesen Trick), wenn die Zahl nicht Null ist.

Da alles binär ist (Mantisse und Exponenten), sind die Umrechnungen in Dezimalzahlen normalerweise nicht genau. Zahlen wie 0,5, 0,25, 0,75, 0,125 werden genau gespeichert, 0,1 jedoch nicht. Wie andere bereits gesagt haben, verwenden Sie nicht float oder double, sondern int, long, BigInteger oder BigDecimal, wenn Sie Cent genau speichern müssen.

Quellen:

http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers

http://en.wikipedia.org/wiki/Binary64

http://en.wikipedia.org/wiki/Binary32

Marcus
quelle
Was meinst du mit 6 bis 9? Wie kann es sich ändern? Wenn ich also mehrmals Code mit 8 Dezimalstellen wie 0,000000001 ausführe, erhalte ich unterschiedliche Ergebnisse? meinst Du das?
Aequitas
1
Einige Zahlen können genauer binär dargestellt werden als andere. Sie können den Unterschied zwischen 0,125 (1/8, acht ist eine Zweierpotenz) und 0,1 (1/10, zehn ist keine Zweierpotenz) erkennen. Ersteres hat mehr (Dezimal-) Stellen, wird aber genau dargestellt. Es kann also sein, dass eine Zahl mit 6 Dezimalstellen größere Rundungsfehler aufweist als eine andere Zahl mit 8 Ziffern.
Marcus
9
15,9 Dezimalstellen für doubleund 7,2 für float, dh 15 und 7. Es können jeweils einige größere Zahlen dargestellt werden, und keine davon gilt für Brüche, aber es gibt keinen "Durchschnitt", und keine Ihrer Quellen sagt dies aus Andernfalls.
Marquis von Lorne
1
Wenn Ihnen das Wort Durchschnitt nicht gefällt, schlagen Sie eine Bearbeitung vor. Es wurde von mir überhaupt nicht hinzugefügt, es wurde von jemand anderem bearbeitet ... (und ich sah wirklich keine Notwendigkeit für diese Bearbeitung).
Marcus
4
Interessanterweise gibt es tatsächlich eine Ziffer mehr Präzision als in der Mantisse / dem Signifikanten gespeichert. 23 und 52 Bits werden für float bzw. double gespeichert, aber da die Zahlen normalisiert sind, können wir ein führendes 1-Bit annehmen und es dann weglassen. Aus diesem Grund beträgt die effektive Genauigkeit 24 bzw. 53 Bit. Die genauen Dezimalgenauigkeiten werden berechnet log10 (2 ^ 24) = 7,22 und log10 (2 ^ 53) = 15,95
Georgie
32

Ein 32-Bit-Float hat eine Genauigkeit von ungefähr 7 Stellen und ein 64-Bit-Double hat eine Genauigkeit von ungefähr 16 Stellen

Lange Antwort:

Gleitkommazahlen bestehen aus drei Komponenten:

  1. Ein Vorzeichenbit, um festzustellen, ob die Zahl positiv oder negativ ist.
  2. Ein Exponent, um die Größe der Zahl zu bestimmen .
  3. Ein Bruch, der bestimmt, wie weit die Zahl zwischen zwei Exponentenwerten liegt. Dies wird manchmal als "Signifikand, Mantisse oder Koeffizient" bezeichnet.

Im Wesentlichen funktioniert dies zu sign * 2^exponent * (1 + fraction). Die „Größe“ der Zahl, ihr Exponent, ist für uns irrelevant, da sie nur den Wert des Bruchteils skaliert . Wenn wir wissen, dass dies log₁₀(n)die Anzahl der Ziffern von n† ergibt, können wir die Genauigkeit einer Gleitkommazahl mit bestimmen log₁₀(largest_possible_fraction). Da jedes Bit in einem Float zwei Möglichkeiten speichert, kann eine binäre Anzahl von nBits eine Zahl bis zu speichern 2ⁿ - 1(insgesamt 2ⁿ Werte, bei denen einer der Werte Null ist). Dies wird etwas haariger, da sich herausstellt, dass Gleitkommazahlen mit einem Bruchteil weniger gespeichert werden, als sie verwenden können, da Nullen speziell dargestellt werden und alle Nicht-Null-Zahlen mindestens ein Nicht-Null-Binärbit haben. ‡

In Kombination ergibt sich die Genauigkeit für eine Gleitkommazahl log₁₀(2ⁿ), wobei ndie Anzahl der Bits des Bruchteils der Gleitkommazahl ist. Ein 32-Bit-Float hat 24 Bruchbits für eine Genauigkeit von 7,22 Dezimalstellen, und ein 64-Bit-Doppel hat 53 Bruchstellen für eine Genauigkeit von 15,95 Dezimalstellen.

Weitere Informationen zur Gleitkomma-Genauigkeit finden Sie im Konzept eines Maschinen-Epsilons .


n ≥ 1Zumindest für andere Zahlen sieht Ihre Formel eher so aus ⌊log₁₀(|n|)⌋ + 1.

‡ „Diese Regel wird verschiedentlich als Leitbitkonvention, implizite Bitkonvention oder Hidden-Bit-Konvention bezeichnet.“ ( Wikipedia )

9999 Jahre
quelle
17

Aus der Java-Spezifikation :

Die Gleitkommatypen sind Gleitkomma- und Doppeltypen, die konzeptionell mit den IEEE 754-Werten und -Operationen im 32-Bit- und 64-Bit-Format mit einfacher Genauigkeit gemäß IEEE-Standard für binäre Gleitkomma-Arithmetik, ANSI / IEEE, verknüpft sind Standard 754-1985 (IEEE, New York).

Da es schwierig ist, mit Zahlen etwas zu tun, ohne die Grundlagen von IEEE754 zu verstehen, finden Sie hier einen weiteren Link .

Es ist wichtig zu verstehen, dass die Genauigkeit nicht einheitlich ist und dass dies keine exakte Speicherung der Zahlen ist, wie dies für ganze Zahlen der Fall ist.

Ein Beispiel :

double a = 0.3 - 0.1;
System.out.println(a);          

druckt

0.19999999999999998

Wenn Sie eine willkürliche Genauigkeit benötigen (zum Beispiel für finanzielle Zwecke), benötigen Sie möglicherweise Big Decimal .

Denys Séguret
quelle
7

Eine normale mathematische Antwort.

Wenn man versteht, dass eine Gleitkommazahl als einige Bits implementiert ist, die den Exponenten und den Rest darstellen, meistens für die Ziffern (im Binärsystem), hat man die folgende Situation:

Bei einem hohen Exponenten, beispielsweise 10²³, erscheint ein großer Unterschied zwischen zwei benachbarten unterscheidbaren Zahlen, wenn das niedrigstwertige Bit geändert wird. Darüber hinaus bewirkt der Dezimalpunkt der Basis 2, dass viele Zahlen der Basis 10 nur angenähert werden können. 1/5, 1/10 sind endlose Zahlen.

Im Allgemeinen sollten Gleitkommazahlen nicht verwendet werden, wenn Sie sich für signifikante Ziffern interessieren. Verwenden Sie für Geldbeträge mit Berechnung am besten BigDecimal .

Für die Physik sind Gleitkomma- Doppel ausreichend, schwebt fast nie. Darüber hinaus kann der Gleitkommateil von Prozessoren, die FPU, intern sogar etwas mehr Präzision verwenden.

Joop Eggen
quelle
3

Gleitkommazahlen werden mit einer Exponentialform codiert, das heißt so etwas m * b ^ ewie Ganzzahlen überhaupt nicht. Die Frage, die Sie stellen, wäre im Zusammenhang mit Festkommazahlen sinnvoll . Es stehen zahlreiche Festpunkt-Arithmetikbibliotheken zur Verfügung.

In Bezug auf Gleitkomma-Arithmetik: Die Anzahl der Dezimalstellen hängt von der Darstellung und dem Zahlensystem ab. Zum Beispiel gibt es periodische Zahlen ( 0.33333), die keine endliche Darstellung in Dezimalzahl haben, sondern eine in Binärzahl und umgekehrt.

Erwähnenswert ist auch, dass Gleitkommazahlen bis zu einem bestimmten Punkt einen Unterschied von mehr als eins aufweisen, dh value + 1Ausbeuten value, da value + 1sie nicht mit m * b ^ ewhere codiert werden mkönnen bund ein der Länge festgelegt sind. Gleiches gilt für Werte kleiner als 1, dh alle möglichen Codepunkte haben nicht den gleichen Abstand.

Aus diesem Grund gibt es keine Genauigkeit von exakten nZiffern wie bei Festkommazahlen, da nicht jede Zahl mit nDezimalstellen eine IEEE-Codierung hat.

Es gibt ein fast obligatorisches Dokument, das Sie dann lesen sollten und das Gleitkommazahlen erklärt: Was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte .

Scravy
quelle
2
+1 für die Erwähnung "Was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte". Es ist jedoch anzumerken, dass jede Zahl, die eine endliche binäre Bruchdarstellung hat, auch eine endliche Dezimaldarstellung hat. Das Problem geht nur von dezimal nach binär.
Patricia Shanahan
1

Schauen Sie sich an Float.intBitsToFloatund Double.longBitsToDouble, welche Art von Erklärung, wie Bits Gleitkommazahlen entsprechen. Insbesondere sehen die Teile eines Normalen floatungefähr so ​​aus

 s * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW

Dabei sind A ... W 23 Bits - 0s und 1s -, die einen Bruch in Binärform darstellen - s ist +/- 1, dargestellt durch eine 0 bzw. eine 1, und exp ist eine vorzeichenbehaftete 8-Bit-Ganzzahl.

Louis Wasserman
quelle