Daher wäre es verschwenderisch, diese Ziffer fast jede einzelne Zahl mit einem Genauigkeitsbit belegen zu lassen.
Aus diesem Grund haben sie die “Leading Bit Convention” geschaffen:
Gehen Sie immer davon aus, dass die Nummer mit eins beginnt
Aber dann, wie man damit umgeht 0.0? Nun, sie haben beschlossen, eine Ausnahme zu erstellen:
wenn der Exponent 0 ist
und der Bruch ist 0
dann steht die Zahl für Plus oder Minus 0.0
damit die Bytes 00 00 00 00 auch vertreten 0.0was gut aussieht.
Wenn wir nur diese Regeln berücksichtigen, wäre die kleinste darstellbare Zahl ungleich Null:
Exponent: 0
Bruchteil: 1
was in einem Hex-Bruch aufgrund der führenden Bit-Konvention in etwa so aussieht:
1.000002 * 2 ^ (-127)
wo .000002 ist 22 Nullen mit a 1 Am Ende.
Wir können nicht nehmen fraction = 0sonst wäre diese Nummer 0.0.
Aber dann dachten sich die Ingenieure, die auch ein feines Gespür für Ästhetik hatten: Ist das nicht hässlich? Dass wir geradeaus springen 0.0 zu etwas, das nicht einmal eine richtige Potenz von 2 ist? Könnten wir nicht noch kleinere Zahlen irgendwie darstellen? (OK, es war ein bisschen besorgniserregender als “hässlich”: Es waren tatsächlich Leute, die schlechte Ergebnisse für ihre Berechnungen erhielten, siehe “Wie Subnormale Berechnungen verbessern” unten).
Subnormale Zahlen
Die Ingenieure kratzten sich eine Weile am Kopf und kamen wie üblich mit einer weiteren guten Idee zurück. Was ist, wenn wir eine neue Regel erstellen:
Wenn der Exponent 0 ist, dann:
das führende Bit wird 0
der Exponent ist auf -126 festgelegt (nicht -127, als ob wir diese Ausnahme nicht hätten)
Solche Zahlen werden subnormale Zahlen (oder denormale Zahlen, was Synonym ist) genannt.
Diese Regel impliziert sofort, dass die Zahl so ist, dass:
Exponent: 0
Bruchteil: 0
ist immer noch 0.0was ziemlich elegant ist, da es eine Regel weniger bedeutet, die Sie im Auge behalten müssen.
Damit 0.0 ist nach unserer Definition eigentlich eine subnormale Zahl!
Mit dieser neuen Regel ist dann die kleinste nicht-subnormale Zahl:
Exponent: 1 (0 wäre subnormal)
Bruchteil: 0
welches darstellt:
1.0 * 2 ^ (-126)
Dann ist die größte subnormale Zahl:
Exponent: 0
Bruchteil: 0x7FFFFF (23 Bit 1)
was gleich ist:
0.FFFFFE * 2 ^ (-126)
wo .FFFFFE ist wieder 23 Bits eins rechts vom Punkt.
Das ist ziemlich nah an der kleinsten nicht-subnormalen Zahl, die vernünftig klingt.
Und die kleinste subnormale Zahl ungleich Null ist:
Exponent: 0
Bruchteil: 1
was gleich ist:
0.000002 * 2 ^ (-126)
was auch ziemlich nah aussieht 0.0!
Unfähig, einen vernünftigen Weg zu finden, Zahlen kleiner als diese darzustellen, waren die Ingenieure glücklich und kehrten zurück, um Katzenbilder online anzusehen, oder was auch immer sie stattdessen in den 70er Jahren taten.
Wie Sie sehen können, gehen subnormale Zahlen einen Kompromiss zwischen Genauigkeit und Darstellungslänge ein.
Als extremstes Beispiel die kleinste Subnormale ungleich Null:
0.000002 * 2 ^ (-126)
hat im Wesentlichen eine Genauigkeit von einem einzelnen Bit anstelle von 32 Bit. Wenn wir zum Beispiel durch zwei teilen:
0.000002 * 2 ^ (-126) / 2
erreichen wir tatsächlich 0.0 exakt!
Visualisierung
Es ist immer eine gute Idee, eine geometrische Intuition für das zu haben, was wir lernen, also los geht’s.
Wenn wir IEEE 754-Gleitkommazahlen für jeden gegebenen Exponenten auf einer Linie darstellen, sieht das ungefähr so aus:
In addition to exposing all of C’s APIs, C++ also exposes some extra subnormal related functionality that is not as readily available in C in <limits>, e.g.:
denorm_min: Returns the minimum positive subnormal value of the type T
In C++ the whole API is templated for each floating point type, and is much nicer.
Implementations
x86_64 and ARMv8 implemens IEEE 754 directly on hardware, which the C code translates to.
Subnormals seem to be less fast than normals in certain implementations: Why does changing 0.1f to 0 slow down performance by 10x? This is mentioned in the ARM manual, see the “ARMv8 details” section of this answer.
The performance of floating-point processing can be reduced when doing calculations involving denormalized numbers and Underflow exceptions. In many algorithms, this performance can be recovered, without significantly affecting the accuracy of the final result, by replacing the denormalized operands and intermediate results with zeros. To permit this optimization, ARM floating-point implementations allow a Flush-to-zero mode to be used for different floating-point formats as follows:
For AArch64:
If FPCR.FZ==1, then Flush-to-Zero mode is used for all Single-Precision and Double-Precision inputs and outputs of all instructions.
If FPCR.FZ16==1, then Flush-to-Zero mode is used for all Half-Precision inputs and outputs of floating-point instructions, other than:—Conversions between Half-Precision and Single-Precision numbers.—Conversions between Half-Precision and Double-Precision numbers.
A1.5.2 “Floating-point standards, and terminology” Table A1-3 “Floating-point terminology” confirms that subnormals and denormals are synonyms:
This manual IEEE 754-2008
------------------------- -------------
[...]
Denormal oder denormalisiertes Subnormal
C5.2.7 „FPCR, Floating-point Control Register“ beschreibt, wie ARMv8 optional Ausnahmen auslösen oder Flag-Bits setzen kann, wenn die Eingabe einer Fließkommaoperation subnormal ist:
FPCR.IDE, bisschen [15] Geben Sie Denormal Floating-Point Exception Trap enable ein. Mögliche Werte sind:
0b0 Nicht abgefangene Ausnahmebehandlung ausgewählt. Wenn die Gleitkomma-Ausnahme auftritt, wird das FPSR.IDC-Bit auf 1 gesetzt.
0b1 Abgefangene Ausnahmebehandlung ausgewählt. Wenn die Gleitkommaausnahme auftritt, aktualisiert das PE das FPSR.IDC-Bit nicht. Die Trap-Handling-Software kann entscheiden, ob das FPSR.IDC-Bit auf 1 gesetzt wird.
D12.2.88 “MVFR1_EL1, AArch32 Media and VFP Feature Register 1” zeigt, dass denormale Unterstützung tatsächlich vollständig optional ist, und bietet ein bisschen, um zu erkennen, ob Unterstützung vorhanden ist:
FPFtZ, Bits [3:0]
Auf Null spülen. Gibt an, ob die Gleitkommaimplementierung nur Unterstützung für den Flush-to-Zero-Betriebsmodus bereitstellt. Definierte Werte sind:
0b0000 Nicht implementiert oder Hardware unterstützt nur den Betriebsmodus „Flush-to-Zero“.
[S]Unnormale Zahlen eliminieren einen Unterlauf als Grund zur Besorgnis bei einer Vielzahl von Berechnungen (normalerweise Multiplizieren gefolgt von Addieren). … Die Klasse der Probleme, die bei einem allmählichen Unterlauf erfolgreich sind, aber bei Store 0 scheitern, ist größer, als die Fans von Store 0 vielleicht erkennen. … In Ermangelung eines allmählichen Unterlaufs müssen Benutzerprogramme empfindlich auf die implizite Ungenauigkeitsschwelle reagieren. Wenn beispielsweise bei einfacher Genauigkeit in einigen Teilen einer Berechnung ein Unterlauf auftritt und Store 0 verwendet wird, um untergelaufene Ergebnisse durch 0 zu ersetzen, kann die Genauigkeit nur bis etwa 10-31 garantiert werden, nicht 10-38, dem üblichen unteren Bereich für Exponenten mit einfacher Genauigkeit.
Der Numerical Computation Guide verweist den Leser auf zwei weitere Artikel:
Zitat für “Beim Entwerfen von IEEE 754 …”? Oder besser den Satz mit ‘Angeblich’ beginnen
– Schrittmacher
28. Mai 2019 um 20:53 Uhr
@ Pacerier Ich glaube nicht, dass diese Tatsache falsch sein kann 🙂 Welche andere Begründung könnte es dafür geben? Wahrscheinlich war das vorher bekannt, aber das ist in Ordnung, denke ich.
– Ciro Santilli 新疆再教育营六四事件法轮功郝海东
28. Mai 2019 um 21:02 Uhr
Tolle Antwort. Ich bereite mich darauf vor, im Frühjahr einen Kurs zur numerischen Analyse zu unterrichten, und werde meine Schüler darauf hinweisen (unser Text enthält eine kurze Diskussion, lässt aber Details aus). Zur Begründung einiger Entscheidungen fand ich folgendes aufschlussreich: Ein Interview mit dem alten Mann von Floating-Point.
– John Colemann
6. Januar 2021 um 17:18 Uhr
“Für jeden Exponenten haben wir die gleiche Anzahl 2^32 von Zahlen (hier dargestellt durch 4 *)” Meinten Sie nicht 2^23 (da es Bruchteile von 23 Bits gibt)?
– Maggyero
9. Februar 2021 um 20:29 Uhr
@Maggyero ja, danke! Mein Gehirn hat gerade 23 in die üblichere 32 umgewandelt 🙂
– Ciro Santilli 新疆再教育营六四事件法轮功郝海东
9. Februar 2021 um 20:43 Uhr
Kerrek SB
Im IEEE754-Standard werden Gleitkommazahlen als binäre wissenschaftliche Notation dargestellt, x = m × 2e. Hier m ist der Mantisse und e ist der Exponent. Mathematisch kann man den Exponenten immer so wählen, dass 1 ≤ ist m < 2.* Da der Exponent in der Computerdarstellung aber nur einen endlichen Bereich haben kann, gibt es einige Zahlen, die größer als Null, aber kleiner als 1,0 × 2 sindeMindest. Diese Zahlen sind die Subnormale oder Denormale.
Praktischerweise wird die Mantisse ohne die führende 1 gespeichert, da es immer eine führende 1 gibt, außer für subnormale Zahlen (und Null). Die Interpretation lautet also: Wenn der Exponent nicht minimal ist, gibt es eine implizite führende 1, und wenn der Exponent minimal ist, gibt es keine, und die Zahl ist subnormal.
*) Allgemeiner 1 ≤ m < B für jede basis-B wissenschaftliche Schreibweise.
Sagst du isnomal ist true wenn die 8 Bits alle Null sind und false Andernfalls?
– Schrittmacher
28. Mai 2019 um 20:45 Uhr
„gespeichert“ oder interpretiert?
– Schrittmacher
28. Mai 2019 um 21:07 Uhr
@Pacerier: “gespeichert”: Es wird ohne führende 1 gespeichert, zB als 001010und interpretiert als 1.001010.
– Kerrek SB
31. Mai 2019 um 9:31 Uhr
Ist es offensichtlich, was das erwähnte emin in ist: “` emin ? “` (Ich hoffe, mein Formatierungsversuch funktioniert)..
Es gibt möglicherweise mehrere Möglichkeiten, dieselbe Zahl darzustellen. Am Beispiel der Dezimalzahl könnte die Zahl 0,1 als 1 * 10 dargestellt werden-1 oder 0,1*100 oder sogar 0,01 * 10. Der Standard schreibt vor, dass die Zahlen immer mit dem ersten Bit als Eins gespeichert werden. Dezimal entspricht das der 1*10-1 Beispiel.
Nehmen wir nun an, dass der niedrigste darstellbare Exponent -100 ist. Die kleinste in Normalform darstellbare Zahl ist also 1*10-100. Wenn wir jedoch die Einschränkung lockern, dass das führende Bit eine Eins sein muss, können wir tatsächlich kleinere Zahlen im selben Raum darstellen. In einem Dezimalbeispiel könnten wir 0,1*10 darstellen-100. Dies wird als subnormale Zahl bezeichnet. Der Zweck subnormaler Zahlen besteht darin, die Lücke zwischen der kleinsten normalen Zahl und Null zu glätten.
Es ist sehr wichtig zu wissen, dass subnormale Zahlen mit weniger Genauigkeit dargestellt werden als normale Zahlen. Tatsächlich tauschen sie reduzierte Präzision für ihre kleinere Größe. Daher haben Berechnungen, die subnormale Zahlen verwenden, nicht die gleiche Genauigkeit wie Berechnungen mit normalen Zahlen. Daher ist eine Anwendung, die signifikante Berechnungen mit subnormalen Zahlen durchführt, wahrscheinlich eine Untersuchung wert, um zu sehen, ob eine Neuskalierung (dh Multiplizieren der Zahlen mit einem Skalierungsfaktor) weniger subnormale und genauere Ergebnisse liefern würde.
9108600cookie-checkWas ist eine subnormale Gleitkommazahl?yes
Das erste Google-Ergebnis zeigt, dass es nur ein Synonym für ein Denormal ist: en.wikipedia.org/wiki/Denormal_number
– zehn vier
1. Dezember 2011 um 12:32 Uhr
Und doch, jetzt der 2. Treffer bei Google (Suche nach „subnormal Floating Point“) ist diese Frage selbst.
– Slipp D. Thompson
30. März 2013 um 18:09 Uhr
Siehe diese Frage für eine ausführliche Diskussion über Denormalitäten und den Umgang mit ihnen: stackoverflow.com/questions/9314534/…
– Feige
26. Februar 2014 um 14:43 Uhr