Der minimale positive Gleitkommawert durch direkte Berechnung unterscheidet sich von FLT_MIN in

Lesezeit: 6 Minuten

Benutzer-Avatar
Shanghai Huang

Ich möchte direkt den Mindestwert von berechnen float Typ, und hier ist mein Algorithmus (Angenommen, die Codierung der Gleitkommazahl entspricht dem IEEE 754-Standard):

#include <math.h>
#include <limits.h>
#include <float.h>
#include <stdio.h>

float float_min()
{
    int exp_bit = CHAR_BIT * sizeof(float) - FLT_MANT_DIG;
    float exp = 2 - pow(2, exp_bit - 1);

    float m = pow(2, -(FLT_MANT_DIG - 1));

    return m * pow(2, exp);
}

int main()
{
    printf("%g\n", float_min());
}

Die Ausgabe ist 1.4013e-45. Allerdings finde ich das den Wert von FLT_MIN in dem C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\float.h ist 1.175494351e-38F. Wer ist falsch?

  • Haben Sie den Code schrittweise durchlaufen, um zu überprüfen, ob die Werte aller Zwischenvariablen Ihren Vorstellungen entsprechen? Und dass die endgültige Berechnung in der return -Anweisung trägt nicht zu den Rundungsproblemen bei? Oder dass die Umstellung auf a double für die printf anrufen ist kein problem?

    – Irgendein Programmierer-Typ

    15. August 2017 um 12:30 Uhr


  • Ihr Code gibt 0 für mich zurück: ideone.com/94xHPT

    – zwischenjay

    15. August 2017 um 12:32 Uhr

  • @interjay Versuchen Sie, signifikantere Zahlen hinzuzufügen, wie z %.50f.

    – Josef Thomson

    15. August 2017 um 12:33 Uhr

  • Informieren Sie sich auch über denormale/subnormale Gleitkommazahlen.

    – Gen

    15. August 2017 um 12:34 Uhr


  • Sie können den Code bearbeiten. Und bitte posten Sie keinen Code, den Sie nicht getestet haben.

    – zwischenjay

    15. August 2017 um 12:35 Uhr

Benutzer-Avatar
Peter Becker

Obwohl diese Frage schon mehrmals gestellt und beantwortet wurde, sehe ich keine Antwort, die wirklich richtig ist. Der Schlüssel ist das FLT_MIN ist am kleinsten normalisiert darstellbarer Wert. Früher war das alles, was zählte. Dann kam Intel und stellte es vor unternormal Werte, die die Genauigkeit reduzieren, um Werte näher an 0 darzustellen. Subnormale sind Werte mit dem minimalen Exponenten und einem Bruchteil, dessen hohe Bits alle Nullen sind. Daraus folgt, dass der kleinste subnormale Wert ungleich Null einen Bruchteil hat, der alle aus Nullen besteht, mit Ausnahme des niedrigsten Bits, das eine 1 ist. Das ist der kleinste Wert, der dargestellt werden kann, aber wenn Sie dort unten sind, ändern Sie sich hier ein wenig und da macht a groß Wertänderung, daher müssen diese Dinge mit großer Sorgfalt verwendet werden.

EDIT, um “Normalisierung” zu verdeutlichen:

Angenommen, wir schreiben Dezimalwerte: 6,02 x 10 ^ 23, 0,602 * 10 ^ 24, 60,2 * 10 ^ 22. Diese stellen alle den gleichen Wert dar, sehen aber deutlich unterschiedlich aus. Führen wir also eine Regel zum Schreiben von Dezimalwerten ein: Jeder Wert muss links vom Dezimalkomma genau eine Nicht-Null-Stelle haben. Die „normalisierte“ Form dieses Werts ist also 6,02 x 10 ^ 23, und wenn wir einen Wert in einer nicht normalisierten Form haben, können wir das Dezimalkomma verschieben und den Exponenten anpassen, um den Wert beizubehalten, und ihn in normalisierte Form bringen.

IEEE-Gleitkomma macht dasselbe: Die Regel lautet, dass das hohe Bit des Bruchs immer 1 sein muss, und jede Berechnung muss den Bruch und den Exponenten ihres Ergebnisses anpassen, um diese Regel zu erfüllen.

Wenn wir Dezimalwerte schreiben, die wirklich nahe bei 0 liegen, ist das kein Problem: Wir können den Exponenten so klein wie nötig machen, sodass wir Zahlen wie 6,02*10^-16384 schreiben können. Mit Fließkommawerten können wir das nicht: Es gibt einen minimalen Exponenten, den wir nicht unterschreiten können. Um kleinere Werte zuzulassen, besagen die IEEE-Anforderungen, dass, wenn der Exponent der kleinste darstellbare Wert ist, der Bruch nicht normalisiert werden muss, das heißt, er muss keine 1 in seinem hohen Bit haben. Beim Schreiben von Dezimalwerten ist das so, als würde man sagen, dass wir eine 0 links vom Dezimalpunkt haben können. Wenn also unsere Dezimalregel besagt, dass der niedrigste zulässige Exponent -100 ist, wäre der kleinste normalisierte Wert 1,00 x 10^-100, aber kleinere Werte könnten als nicht normalisiert dargestellt werden: 0,10*10^-100, 0,01*10^- 100 usw.

Fügen Sie nun eine Anforderung zu unseren Dezimalregeln hinzu, dass wir nur drei Ziffern haben können: eine links vom Dezimalkomma und zwei rechts. Das ist wie der Gleitkommabruch, da er eine feste Anzahl von Ziffern hat. Für kleine Normalwerte haben wir also drei Ziffern, mit denen wir spielen können: 1,23*10^-100. Für kleinere Werte verwenden wir führende Nullen und die verblieben Ziffern haben weniger Genauigkeit: 0,12*10^-100 hat zwei Ziffern und 0,01*10^-100 hat nur 1. So funktionieren auch Gleitkomma-Subnormale: Sie erhalten immer weniger signifikante Bits, je weiter Sie unter die kommen minimaler normalisierter Wert, bis Ihnen die Bits ausgehen und Sie 0 erhalten.

BEARBEITEN: Um die Terminologie zu verdeutlichen, bezeichnet der IEEE-754-Standard diejenigen Werte, die größer als 0 und kleiner als der normalisierte Mindestwert sind Denormale; die neueste Revision von IEEE-754 bezeichnet sie als Subnormale. Sie meinen dasselbe.

  • Irgendeine Referenz für die Behauptung, dass es Intel war, der Denormals eingeführt hat? Ich kann anscheinend keinen finden.

    – Ruslan

    15. August 2017 um 15:04 Uhr

  • @Ruslan William Kahan führte Denormals (mit Jerome Coonen und Harold Stone) in den KCS-Entwurf ein. Kahan wurde damals von Intel als Berater bezahlt, um den 8087 zu entwerfen. Ein Teil der Geschichte wird hier erzählt: blogs.mathworks.com/cleve/2014/07/21/…

    – Pascal Cuoq

    15. August 2017 um 15:07 Uhr

  • Ich frage mich, wie die Kosten für die Unterstützung von Denormalen im Vergleich zu den Kosten für das Erzwingen der Rundung kleiner Werte auf ein Inkrement gleich dem kleinsten normalisierten Wert liegen würden (z. B. wenn der kleinste normalisierte Float 2^-127 wäre, addiere und subtrahiere dann 2^- 104), wenn ein Wert positiv und kleiner als dieser ist, oder subtrahieren und dann addieren, wenn der Wert negativ und klein war).

    – Superkatze

    15. August 2017 um 18:29 Uhr


  • @supercat: Es gibt sehr gute Gründe für die Existenz von Denormalen. Sie auf Normalwerte zu runden oder auf Null zu spülen, beeinträchtigt die numerischen Stabilitätseigenschaften in einigen wichtigen Anwendungen erheblich. Es gibt gute Erklärungen dafür (vielleicht sogar in “Was jeder wissen sollte …”), aber ich habe keine Liste mit Links, die ich Ihnen geben könnte.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    15. August 2017 um 20:15 Uhr

  • @R..: Es ist äußerst wünschenswert, dass die kleinstmögliche Differenz zwischen zwei Float-Werten darstellbar ist; das wird typischerweise unter Verwendung von Denormalen erreicht, aber andere Ansätze wären ebenso verwendbar. Die von mir vorgeschlagene Rundung würde 23 Bit Dynamikbereich verlieren float im Vergleich zur Unterstützung von Denormals, die etwas lästig wäre, aber die meisten Anwendungen nutzen nicht wirklich den vollen Dynamikbereich, und es könnte billiger sein, sie in Hardware zu unterstützen.

    – Superkatze

    15. August 2017 um 20:26 Uhr

Dein Ergebnis 1.4013e-45 ist ein denormaler minimaler positiver Gleitkommawert, auch bekannt als FLT_TRUE_MIN was gleich ist 1.401298464e-45F.

FLT_MIN ist normalisierter minimaler positiver Gleitkommawert (1.175494351e-38F)

  • Der Vollständigkeit halber nur darauf verweisen: stackoverflow.com/a/25705927/8051589.

    – André Kampling

    15. August 2017 um 12:44 Uhr


  • @kameiha versuchen zu sehen <cfloat>

    – ikleschenkov

    15. August 2017 um 13:27 Uhr

  • @ikleschenkov Nein FLT_TRUE_MIN in <cfloat>.

    – Shangchihhuang

    15. August 2017 um 13:35 Uhr

  • @kameiha das einzige, was a finden konnte, ist eine Ergänzung zum C-Standard: open-std.org/jtc1/sc22/wg14/www/docs/n1378.htm. Sie wissen nicht, warum Ihre C++-Bibliotheken fehlen FLT_TRUE_MIN

    – ikleschenkov

    15. August 2017 um 13:45 Uhr

  • Und das OP verwendet C.

    – Wladimir F. Героям слава

    16. August 2017 um 6:58 Uhr

1187690cookie-checkDer minimale positive Gleitkommawert durch direkte Berechnung unterscheidet sich von FLT_MIN in

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy