Gibt es eine Standard- und / oder tragbare Methode, um den kleinsten negativen Wert (z. B. negative Unendlichkeit) in einem C (++) -Programm darzustellen?
DBL_MIN in float.h ist die kleinste positive Zahl.
Ich werde mich für -DBL_MAX entscheiden, aber ich bin mir sicher, dass es einen technischen Grund gibt, warum dies nicht so ist :-)
4
@Neil, nein, gibt es nicht, es ist nicht wie 2 Komplement-Ganzzahlen
fortran
Ich habe noch nichts im Standard gesehen, was besagt, dass der Bereich der Gleitkommatypen um Null symmetrisch sein muss. Die Konstanten in limit.h und <limits> deuten jedoch darauf hin, dass sowohl der C- als auch der C ++ - Standard dies erwarten.
Steve Jessop
4
Tatsächlich ist DBL_MIN in float.h die kleinste positive normalisierte Zahl. Es gibt Zahlen, die noch kleiner sind.
Fdermishin
1
@fortran: IEEE 754 FP verwendet ein Vorzeichenbit, und die meiste FP-Hardware ist heutzutage IEEE 754. Da C und C ++ jedoch Nicht-IEEE 754 FP-Hardware unterstützen, ist die Frage offen, ob die Sprache die Garantie für -DBL_MAX übernimmt muss gleich dem minimalen darstellbaren Wert sein.
Hier ist die Erklärung für mein -1: Wer oder was sagt, dass -DBL_MAX durch die C- oder C ++ - Sprache als darstellbar garantiert wird, geschweige denn als minimal darstellbarer Wert? Die Tatsache, dass die meisten FP-Hardware IEEE 754-konform ist und diese Darstellung verwendet, bedeutet nicht, dass -DBL_MAX garantiert auf jeder standardkonformen C-Plattform funktioniert.
j_random_hacker
@j_random_hacker: siehe fortrans Antwort 'unten'.
JohnTortugo
3
@j_random_hacker Das ist ein sehr guter Punkt, aber der C-Standard muss -DBL_MAXgenau darstellbar sein. Wenn die FP-Hardware dazu nicht in der Lage ist, muss die Implementierung ihn nur umgehen . Siehe das Gleitkommamodell in 5.2.4.2.2 Eigenschaften der Gleitkommatypen <float.h> p2 von C99 (möglicherweise seitdem an einen anderen Ort verschoben).
2
@j_random_hacker Ja, aber p2 gibt an, dass e_min und e_max unabhängig vom Vorzeichenbit sind, also DBL_MAXgenau (1 - b ^ - p) b ^ e_max, was genau darstellbar ist, der negativste endliche Wert ist genau - (1 - b ^ −p) b ^ e_max, und da dies genau der Fall ist -DBL_MAX, DBL_MAXkann das Negieren auch keine Rundungsfehler verursachen.
70
Gleitkommazahlen (IEEE 754) sind symmetrisch. Wenn Sie also den größten Wert ( DBL_MAXoder numeric_limits<double>::max()) darstellen können, stellen Sie einfach ein Minuszeichen voran.
+1 Für den Hinweis auf die Symmetrie von Gleitkommazahlen :)
Andrew Hare
4
Was ist mit C / C ++ - Implementierungen, die keine IEEE 754-Floats verwenden?
Steve Jessop
1
Das Handbuch von gcc für -ffast-math lautet: "Setzt -fno-math-errno, -funsafe-math-Optimierungen, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans und -fcx-limited- Bereich Diese Option wird von keiner -O-Option aktiviert, da sie zu einer falschen Ausgabe für Programme führen kann, die von einer genauen Implementierung der IEEE- oder ISO-Regeln / Spezifikationen für mathematische Funktionen abhängen. Sie kann jedoch schnelleren Code für Programme liefern, die dies tun erfordern nicht die Garantien dieser Spezifikationen. " Schnelle Mathematik ist eine gängige Einstellung, und der Intel ICC verwendet sie beispielsweise standardmäßig. Alles in allem nicht sicher, was das für mich bedeutet :-)
Will
4
Dies bedeutet, dass Implementierungen keine IEEE 754-Arithmetik verwenden, aber um fair zu sein, verwenden diese Optionen immer noch die IEEE-Darstellung. Möglicherweise finden Sie einige Emulationsbibliotheken, die eine Nicht-IEEE-Darstellung verwenden, da nicht alle Prozessoren ein natives Float-Format haben (obwohl sie möglicherweise ein C ABI veröffentlichen, das ein Format enthält, das den vom Hersteller bereitgestellten Emulationsbibliotheken entspricht). Daher können nicht alle Compiler einen verwenden. Kommt nur darauf an, was du meinst, wenn du nach "Standard und / oder tragbar" fragst, es gibt im Prinzip tragbar und in der Praxis tragbar.
Steve Jessop
3
Was Sie sagen, gilt für IEEE 754, aber der Standard erfordert nicht die Verwendung dieser Codierung (wie @SteveJessop hervorhebt, ist Portable in der Praxis nicht dasselbe wie Portable im Prinzip).
@Alexis: Wenn Sie sich die drei niedrigsten Zeilen in der Tabelle auf der von Ihnen verlinkten Seite ansehen, werden Sie feststellen, dass minSie den kleinsten positiven Wert in der Größe und lowestden größten negativen Wert in der Größe erhalten. Ja, es ist schrecklich. Willkommen in der brillanten Welt der C ++ - Standardbibliothek :-P.
Rubenvb
für C ist es definiert in float.h. limits.hist für ganze Zahlen
Diese Klasse ist auf jeden der grundlegenden Typen spezialisiert, wobei ihre Mitglieder die verschiedenen Werte zurückgeben oder festlegen, die die Eigenschaften definieren, die der Typ in der spezifischen Plattform hat, auf der er kompiliert wird.
Warum nicht einfach -numeric_limits<double>::max()?
k06a
4
@ k06a Wenn die Negation durch ein einzelnes Zeichen in einem so langen Ausdruck dargestellt wird, in dem die Zeichenfolge sogar "max" sagt, wird sicher früher oder später jemand gefunden. Entweder wird es in einer beschreibenden Variablen gespeichert oder verwendet -1 * ..., um es etwas klarer zu machen.
Filip Haglund
20
Suchen Sie nach der tatsächlichen Unendlichkeit oder dem minimalen endlichen Wert? Wenn erstere, verwenden Sie
-numeric_limits<double>::infinity()
was nur funktioniert wenn
numeric_limits<double>::has_infinity
Andernfalls sollten Sie verwenden
numeric_limits<double>::lowest()
Das wurde in C ++ 11 eingeführt.
Wenn lowest()nicht verfügbar, können Sie auf zurückgreifen
-numeric_limits<double>::max()
was lowest()im Prinzip abweichen kann, in der Praxis aber normalerweise nicht.
+1 für die Differenz zwischen endlichem und unendlichem Wert! Der Standard garantiert jedoch keine symetrische Gleitkomma-Codierung. Also -numeric_limits<double>::max()auch wenn es in der Praxis funktioniert , ist nicht vollständig tragbar in der Theorie.
Christophe
@Christophe: [x] behoben
Christoph
10
Eine wirklich tragbare C ++ - Lösung
Ab C ++ 11 können Sie verwenden numeric_limits<double>::lowest(). Gemäß dem Standard gibt es genau das zurück, wonach Sie suchen:
Ein endlicher Wert x, so dass es keinen anderen endlichen Wert y gibt y < x.
Sinnvoll für alle Spezialisierungen, in denen is_bounded != false.
Es gibt viele Antworten -std::numeric_limits<double>::max().
Glücklicherweise funktionieren sie in den meisten Fällen gut. Gleitkomma-Codierungsschemata zerlegen eine Zahl in einer Mantisse und einen Exponenten, und die meisten von ihnen (z. B. das beliebte IEEE-754 ) verwenden ein eindeutiges Vorzeichenbit, das nicht zur Mantisse gehört. Dies ermöglicht es, das größte Positiv in das kleinste Negativ umzuwandeln, indem Sie einfach das Vorzeichen umdrehen:
Warum sind diese nicht tragbar?
Der Standard schreibt keinen Gleitkomma-Standard vor.
Ich stimme zu, dass mein Argument ein wenig theoretisch ist, aber nehmen wir an, dass ein exzentrischer Compilerhersteller ein revolutionäres Codierungsschema mit einer Mantisse verwenden würde, die in einigen Variationen des Zweierkomplements codiert ist . Die Zweierkomplementcodierung ist nicht symmetrisch. Beispielsweise ist für ein vorzeichenbehaftetes 8-Bit-Zeichen das maximale positive 127, das minimale negative -128. Wir könnten uns also vorstellen, dass einige Gleitkomma-Codierungen ein ähnliches asymmetrisches Verhalten zeigen.
Mir ist kein solches Codierungsschema bekannt, aber der Punkt ist, dass der Standard nicht garantiert, dass das Umdrehen der Vorzeichen das beabsichtigte Ergebnis liefert . Diese beliebte Antwort (sorry Leute!) Kann also nicht als vollständig tragbare Standardlösung angesehen werden! / * zumindest nicht, wenn du nicht behauptet hast, dass numeric_limits<double>::is_iec559das wahr ist * /
Gute Idee ! Und es funktioniert . Aber nur wennnumeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
Christophe
1
Gibt es eine Standard- und / oder tragbare Methode, um den kleinsten negativen Wert (z. B. negative Unendlichkeit) in einem C (++) -Programm darzustellen?
C-Ansatz.
Viele Implementierungen unterstützen +/- Unendlichkeiten, daher ist der negativste doubleWert -INFINITY.
#include<math.h>double most_negative =-INFINITY;
Gibt es einen Standard- und / oder tragbaren Weg ....?
Jetzt müssen wir auch andere Fälle berücksichtigen:
Keine Unendlichkeiten
Einfach -DBL_MAX.
Nur eine unsignierte Unendlichkeit.
Ich würde in diesem Fall erwarten, OP würde es vorziehen -DBL_MAX.
De-normale Werte größer als DBL_MAX.
Dies ist ein ungewöhnlicher Fall, der wahrscheinlich außerhalb der Besorgnis von OP liegt. Wenn doublees als Paar von Gleitkommazahlen codiert wird , um den gewünschten Bereich / die gewünschte Präzession zu erreichen (siehe Doppel-Doppel ), gibt es eine maximale Normalendouble und möglicherweise eine größere De-Normalen . Ich habe eine Debatte gesehen, wenn ich mich DBL_MAXauf die größte Normalität beziehen sollte, auf die größte von beiden.
Glücklicherweise enthält dieser gepaarte Ansatz normalerweise eine -Infinity, sodass der negativste Wert erhalten bleibt -INFINITY.
Für mehr Portabilität kann Code die Route entlang gehen
// HUGE_VAL is designed to be infinity or DBL_MAX (when infinites are not implemented)// .. yet is problematic with unsigned infinity.double most_negative1 =-HUGE_VAL;// Fairly portable, unless system does not understand "INF"double most_negative2 = strtod("-INF",(char**) NULL);// Pragmaticdouble most_negative3 = strtod("-1.0e999999999",(char**) NULL);// Somewhat time-consumingdouble most_negative4 = pow(-DBL_MAX,0xFFFF/* odd value */);// My suggestiondouble most_negative5 =(-DBL_MAX)*DBL_MAX;
Wenn Sie keine Float-Ausnahmen aktiviert haben (die Sie nicht imho sollten), können Sie einfach sagen:
double neg_inf =-1/0.0;
Dies ergibt eine negative Unendlichkeit. Wenn Sie einen Float benötigen, können Sie entweder das Ergebnis umwandeln
float neg_inf =(float)-1/0.0;
oder verwenden Sie eine Arithmetik mit einfacher Genauigkeit
float neg_inf =-1.0f/0.0f;
Das Ergebnis ist immer das gleiche, es gibt genau eine Darstellung der negativen Unendlichkeit in einfacher und doppelter Genauigkeit und sie konvertieren wie erwartet ineinander.
Warum sollten Sie dies tun, anstatt nur zu schreiben-INFINITY
MM
Unendlichkeit kann auch existieren oder nicht, und wenn sie existiert, können Positiv und Negativ möglicherweise nicht unterschieden werden (in Standard C).
MM
In vielen Compilern und / oder Architekturen verlangsamt Ihr C / C ++ - Code viele von Ihnen, die Unendlichkeits- und NaN-Werte verbreiten.
Markgalassi
@markgalassi Bitte schauen Sie genauer hin: Sie werden feststellen, dass der Wertneg_inf auf einen konstanten Wert initialisiert ist . Der Compiler kümmert sich um die Berechnung des infWertes. Wenn Sie es als Nullwert für die Berechnung eines Maximums verwenden, wird es bei der ersten Iteration im Allgemeinen mit einem größeren Wert überschrieben. Dh die Leistung ist kaum ein Problem. Und das OP fragt speziell nach "zB negative Unendlichkeit verwenden" und -infist in der Tat die einzig richtige Antwort darauf. Sie haben eine korrekte und nützliche Antwort abgelehnt.
Antworten:
-DBL_MAX
in ANSI C , das in float.h definiert ist.quelle
-DBL_MAX
genau darstellbar sein. Wenn die FP-Hardware dazu nicht in der Lage ist, muss die Implementierung ihn nur umgehen . Siehe das Gleitkommamodell in 5.2.4.2.2 Eigenschaften der Gleitkommatypen <float.h> p2 von C99 (möglicherweise seitdem an einen anderen Ort verschoben).DBL_MAX
genau (1 - b ^ - p) b ^ e_max, was genau darstellbar ist, der negativste endliche Wert ist genau - (1 - b ^ −p) b ^ e_max, und da dies genau der Fall ist-DBL_MAX
,DBL_MAX
kann das Negieren auch keine Rundungsfehler verursachen.Gleitkommazahlen (IEEE 754) sind symmetrisch. Wenn Sie also den größten Wert (
DBL_MAX
odernumeric_limits<double>::max()
) darstellen können, stellen Sie einfach ein Minuszeichen voran.Und dann ist der coole Weg:
quelle
Verwenden Sie in C
Verwenden Sie in C ++ vor 11
Verwenden Sie in C ++ 11 und höher
quelle
min()
Funktion vor C ++ 11 nicht verfügbar? Oder ist das ein anderer Wert als-max()
? en.cppreference.com/w/cpp/types/numeric_limitsmin
Sie den kleinsten positiven Wert in der Größe undlowest
den größten negativen Wert in der Größe erhalten. Ja, es ist schrecklich. Willkommen in der brillanten Welt der C ++ - Standardbibliothek:-P
.float.h
.limits.h
ist für ganze ZahlenVersuche dies:
Referenz:
numeric_limits
quelle
-numeric_limits<double>::max()
?-1 * ...
, um es etwas klarer zu machen.Suchen Sie nach der tatsächlichen Unendlichkeit oder dem minimalen endlichen Wert? Wenn erstere, verwenden Sie
was nur funktioniert wenn
Andernfalls sollten Sie verwenden
Das wurde in C ++ 11 eingeführt.
Wenn
lowest()
nicht verfügbar, können Sie auf zurückgreifenwas
lowest()
im Prinzip abweichen kann, in der Praxis aber normalerweise nicht.quelle
-numeric_limits<double>::max()
auch wenn es in der Praxis funktioniert , ist nicht vollständig tragbar in der Theorie.Eine wirklich tragbare C ++ - Lösung
Ab C ++ 11 können Sie verwenden
numeric_limits<double>::lowest()
. Gemäß dem Standard gibt es genau das zurück, wonach Sie suchen:Online-Demo
Viele nicht portable C ++ - Antworten hier!
Es gibt viele Antworten
-std::numeric_limits<double>::max()
.Glücklicherweise funktionieren sie in den meisten Fällen gut. Gleitkomma-Codierungsschemata zerlegen eine Zahl in einer Mantisse und einen Exponenten, und die meisten von ihnen (z. B. das beliebte IEEE-754 ) verwenden ein eindeutiges Vorzeichenbit, das nicht zur Mantisse gehört. Dies ermöglicht es, das größte Positiv in das kleinste Negativ umzuwandeln, indem Sie einfach das Vorzeichen umdrehen:
Warum sind diese nicht tragbar?
Der Standard schreibt keinen Gleitkomma-Standard vor.
Ich stimme zu, dass mein Argument ein wenig theoretisch ist, aber nehmen wir an, dass ein exzentrischer Compilerhersteller ein revolutionäres Codierungsschema mit einer Mantisse verwenden würde, die in einigen Variationen des Zweierkomplements codiert ist . Die Zweierkomplementcodierung ist nicht symmetrisch. Beispielsweise ist für ein vorzeichenbehaftetes 8-Bit-Zeichen das maximale positive 127, das minimale negative -128. Wir könnten uns also vorstellen, dass einige Gleitkomma-Codierungen ein ähnliches asymmetrisches Verhalten zeigen.
Mir ist kein solches Codierungsschema bekannt, aber der Punkt ist, dass der Standard nicht garantiert, dass das Umdrehen der Vorzeichen das beabsichtigte Ergebnis liefert . Diese beliebte Antwort (sorry Leute!) Kann also nicht als vollständig tragbare Standardlösung angesehen werden! / * zumindest nicht, wenn du nicht behauptet hast, dass
numeric_limits<double>::is_iec559
das wahr ist * /quelle
sollte gut funktionieren
Numerische Grenzen
quelle
Die ursprüngliche Frage betrifft die Unendlichkeit. Also, warum nicht verwenden
nach der IEEE-Definition? Das können Sie natürlich negieren.
quelle
numeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
C-Ansatz.
Viele Implementierungen unterstützen +/- Unendlichkeiten, daher ist der negativste
double
Wert-INFINITY
.Jetzt müssen wir auch andere Fälle berücksichtigen:
Einfach
-DBL_MAX
.Ich würde in diesem Fall erwarten, OP würde es vorziehen
-DBL_MAX
.DBL_MAX
.Dies ist ein ungewöhnlicher Fall, der wahrscheinlich außerhalb der Besorgnis von OP liegt. Wenn
double
es als Paar von Gleitkommazahlen codiert wird , um den gewünschten Bereich / die gewünschte Präzession zu erreichen (siehe Doppel-Doppel ), gibt es eine maximale Normalendouble
und möglicherweise eine größere De-Normalen . Ich habe eine Debatte gesehen, wenn ich michDBL_MAX
auf die größte Normalität beziehen sollte, auf die größte von beiden.Glücklicherweise enthält dieser gepaarte Ansatz normalerweise eine -Infinity, sodass der negativste Wert erhalten bleibt
-INFINITY
.Für mehr Portabilität kann Code die Route entlang gehen
quelle
Wenn Sie keine Float-Ausnahmen aktiviert haben (die Sie nicht imho sollten), können Sie einfach sagen:
Dies ergibt eine negative Unendlichkeit. Wenn Sie einen Float benötigen, können Sie entweder das Ergebnis umwandeln
oder verwenden Sie eine Arithmetik mit einfacher Genauigkeit
Das Ergebnis ist immer das gleiche, es gibt genau eine Darstellung der negativen Unendlichkeit in einfacher und doppelter Genauigkeit und sie konvertieren wie erwartet ineinander.
quelle
-INFINITY
neg_inf
auf einen konstanten Wert initialisiert ist . Der Compiler kümmert sich um die Berechnung desinf
Wertes. Wenn Sie es als Nullwert für die Berechnung eines Maximums verwenden, wird es bei der ersten Iteration im Allgemeinen mit einem größeren Wert überschrieben. Dh die Leistung ist kaum ein Problem. Und das OP fragt speziell nach "zB negative Unendlichkeit verwenden" und-inf
ist in der Tat die einzig richtige Antwort darauf. Sie haben eine korrekte und nützliche Antwort abgelehnt.