13 Stimmen

Wie man Double + Float Präzision berechnet

Ich habe versucht herauszufinden, wie man die Fließkomma-/Doppelpräzisions-/Bereichszahlen berechnen kann -3.402823e38 .. 3.402823e38 und -1.79769313486232e308 .. 1.79769313486232e308.

Für int32 würden Sie tun 2^32=4294967296/2 Sie erhalten einen Bereich von -2147483648 bis 2147483647. Wie finde ich also die Präzisionszahlen für float und double heraus. Ich glaube, ich suche nach den falschen Begriffen, da ich nirgends etwas finde.

27voto

Joey Punkte 329386

Nun, beide Arten sehen eigentlich wie folgt aus:

[sign] [exponent] [mantissa]

die eine Zahl in der folgenden Form darstellt:

[Vorzeichen] 1.[Mantisse] × 2 [Exponent]

wobei die Größe des Exponenten und der Mantisse variiert. Für float der Exponent ist acht Bit breit, während double hat einen Elf-Bit-Exponenten. Außerdem wird der Exponent vorzeichenlos mit einem Vorspannung die 127 für float und 1023 für double . Daraus ergibt sich ein Bereich für den Exponenten von -126 bis 127 für float und -1022 bis 1023 für double .

Der Exponent ist der Exponent für 2 etwas so dass bei der Berechnung von 2 127 erhalten Sie 1,7 × 10 38 was Sie in den ungefähren Bereich der float Höchstwert. Ähnlich für double mit 9 × 10 307 .

Offensichtlich sind diese Zahlen nicht genau das, was wir erwarten. An dieser Stelle kommt die Mantisse ins Spiel. Die Mantisse steht für eine normalisiert Binärzahl, die immer beginnt mit "1". (das ist der normalisierte Teil). Der Rest sind einfach die Ziffern nach dem Punkt. Da die maximale Mantisse dann ungefähr 1.111111111 ist... im Binärformat que es fast 2, erhalten wir etwa 3,4 × 10 38 als float den Höchstwert und 1,79 × 10 308 als Höchstwert für double .

[BEARBEITEN 2011-01-06] Wie Mark weiter unten (und unter der Frage) darlegt, lautet die genaue Formel wie folgt:

Formula to calculate the exact maximum value for an IEEE-754 floating-point type: 2^(2^(e-1) )(1-2^(-p) )

wobei e ist die Anzahl der Bits im Exponenten und p ist die Anzahl der Bits in der Mantisse, einschließlich das oben erwähnte implizite Bit (aufgrund der Normalisierung). Die Formel entspricht dem, was wir oben gesehen haben, nur jetzt genauer. Der erste Faktor, 2 2 e - 1 ist der maximale Exponent, multipliziert mit zwei (wir speichern die zwei dann im zweiten Faktor). Der zweite Faktor ist die größte Zahl, die wir darstellen können unter einem . Ich sagte oben, dass die Zahl fast zwei . Da wir in dieser Formel den Exponenten um den Faktor zwei übertrieben haben, müssen wir dies berücksichtigen und haben nun eine Zahl, die fast eins . Ich hoffe, es ist nicht zu verwirrend.

In jedem Fall ist für float (mit e \= 8 und p \= 24) erhalten wir den genauen Wert 340282346638528859811704183484516925440 oder etwa 3,4 × 10 38 . double ergibt sich dann (mit e \= 10 und p \= 53) 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368 oder ungefähr 1. 80 × 10 308 .

[/EDIT]

Und noch etwas: Sie erwähnen in Ihrer Frage den Begriff "Präzision", aber Sie zitieren die Bereiche der Typen. Die Präzision ist eine ganz andere Sache und bezieht sich darauf, wie viele signifikante Stellen der Typ behalten kann. Auch hier liegt die Antwort in der Mantisse, die 23 und 52 Bits beträgt für float y double . Da die Zahlen normalisiert gespeichert werden, kommt noch ein implizites Bit hinzu, so dass wir auf 24 und 53 Bits kommen. Die Funktionsweise der Ziffern nach dem Dezimalpunkt (oder hier binär) ist die folgende:

 1.   1     0     1     1

2^0  2^-1  2^-2  2^-3  2^-4
 =    =     =     =     =
 1   0.5   0.25  0.125 0.0625

Die allerletzte Ziffer der double Die Mantisse entspricht einem Wert von etwa 2,2 × 10 -16 oder 2 -52 Wenn also der Exponent 1 ist, ist dies der kleinste Wert, den wir zu der Zahl addieren können, indem wir die double Genauigkeit von 16 Dezimalstellen. Gleichermaßen für float mit etwa sieben Ziffern.

0voto

Olof Forshell Punkte 3071

Ich habe das Fließkommaformat unter verschiedenen (wenn auch natürlich nicht allen) Aspekten besprochen. Diese Antwort könnte Ihnen helfen: https://stackoverflow.com/questions/4851671/printing-double-without-losing-precision

-1voto

davogotland Punkte 2687

Das ist nicht so einfach zu berechnen. das liegt an der art und weise, wie floats und doubles implementiert sind. sie sind beide in zwei teile geteilt: ein teil für die basiszahl und ein teil für den exponenten. ich glaube, float wird in 24 bits zur basiszahl und 8 bits zum exponenten geteilt. aber ich bin mir da nicht sicher! ich werde meine weiteren berechnungen und annahmen auf diese tatsache stützen. diese berechnungen können also alle falsch sein, aber sie veranschaulichen die richtigen prinzipien. diese spezifikationen können sich auch von sprache zu sprache unterscheiden, obwohl es standards gibt, die besagen, dass dies nicht der fall sein sollte. aber beim programmieren kann nichts als selbstverständlich angesehen werden :p

Das bedeutet, dass die Basiszahl zwischen -8388608 und 8388607 liegen kann und der Exponent zwischen -128 und 127 liegen kann.

Wenn die Nummer dann verwendet wird, denkt der Computer wie folgt:

Basis * 10^Exponent

was dazu führt, dass die größtmögliche Zahl 8388607 * 10 ^ 127 ist, was... eine Menge wäre. Aber sie würde 120 Nullen enthalten, weil sie nicht mehr als 7 weitere Zahlen angeben kann.

die genauigkeit der zahl wird mit zunehmender zahl geringer. das bedeutet, dass deine frage schlecht formatiert ist ;) du kannst nur dann einen gültigen bereich für einen float angeben, wenn du weißt, wie viele korrekte dezimalstellen benötigt werden. wenn du die möglichkeit von 2 garantiert genauen dezimalstellen brauchst, dann hätte float einen bereich von -83885 bis 83885.

-2voto

Greg McNulty Punkte 1466

Der Typ Float kann Werte im Bereich von etwa 1,5 × 10 45 auf 3,4 × 10 38 mit einer Genauigkeit von 7 Ziffern.

Der Typ double kann Werte von etwa 5,0 × 10 324 auf 1,7 × 10 308 mit einer Genauigkeit von 15-16 Ziffern.

http://msdn.microsoft.com/en-us/library/aa691146%28v=vs.71%29.aspx

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X