Wie generiert man NaN, -Infinity und +Infinity in ANSI C?

Lesezeit: 3 Minuten

Benutzeravatar von Amir Saniyan
Amir Saniyan

Ich verwende ANSI C89 (nicht C++) und möchte generieren NaN, -Infinity und +Infinity.

Gibt es einen Standardweg (z. B. Standardmakro)? Oder gibt es eine Plattform- und Compiler-unabhängige Möglichkeit, diese Zahlen zu generieren?

float f = 0.0 / 0.0; // Is f ALWAYS in any platform is NaN?

  • Beliebige Plattformen werden vom Standard nicht einmal gefordert, um NaNs und Unendlichkeiten zu unterstützen. Ich glaube jedoch, dass eine IEEE 754-konforme Implementierung erforderlich ist, um sie wie in Ihrem Beispiel durch Division zu erhalten.

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

    4. Juni 2011 um 12:23 Uhr

Benutzeravatar von Mat
Matte

Es gibt in C99, aber nicht in früheren Standards AFAIK.

In C99 haben Sie NAN und INFINITY Makros.

Aus “Mathematik <math.h> (§7.12) Abschnitt

Das Makro UNENDLICHKEIT erweitert sich zu einem konstanten Ausdruck vom Typ Float, der positive oder vorzeichenlose Unendlichkeit darstellt, falls verfügbar; …

Wenn Sie bei ANSI C89 hängen bleiben, haben Sie Pech. Sehen C-FAQ 14.9.

  • Sie sollten “ANSI C89” sagen. Das aktuelle “ANSI C” ist C99.

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

    4. Juni 2011 um 12:24 Uhr

  • In C89 das Makro HUGE_VAL ist verfügbar, um unendliche Werte zu definieren.

    – mlel

    16. April 2018 um 14:33 Uhr

  • @R..GitHubSTOPHELPINGICE ANSI hat ISO C99 im Jahr 2000 übernommen. Das aktuelle C ist jedoch ISO C18 (oder manchmal C17) und ANSI C18.

    – FrankHB

    7. Februar um 1:10

Ich weiß nicht, ob dies Standard oder portabel ist, aber hier ist ein Anfang:

jcomeau@intrepid:/tmp$ cat test.c; make test; ./test
#include <stdio.h>
int main() {
 printf("%f\n", 1.0 / 0);
 printf("%f\n", -1.0 / 0);
 printf("%f\n", 0.0 / 0);
 return 0;
}
cc     test.c   -o test
test.c: In function ‘main’:
test.c:3: warning: division by zero
test.c:4: warning: division by zero
test.c:5: warning: division by zero
inf
-inf
-nan

Seltsamerweise kann ich mit diesem naiven Ansatz kein positives NaN erhalten.


Siehe auch das: http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

  • lustig, das produziert inf -inf nan (nicht -nan) mit Klirren. nicht wirklich sicher, was -nan soll eigentlich heißen 🙂

    – Matte

    4. Juni 2011 um 9:23 Uhr

  • Ergebnis von VS2010: 1.#INF00 -1.#INF00 -1.#IND00

    – Amir Saniyan

    4. Juni 2011 um 9:37 Uhr

  • Was bedeuten 1.#INF00, -1.#IND00 und -1.#IND?

    – phuklv

    10. April 2015 um 10:39 Uhr

  • @Mat Jeder Float hat immer ein Vorzeichenbit. Sie können positive NaN (oder jede andere Zahl) für Float erhalten f mit f | (1 << 31).

    – Nearoo

    24. November 2018 um 10:33 Uhr


  • Bekommen -NaNverwenden -(0.f/0.f).

    – SS Anne

    17. August 2019 um 18:58 Uhr

mlels Benutzeravatar
mlel

Wenn Sie einen alten Compiler verwenden, wo INFINITY nicht existiert, können Sie auch das Makro verwenden HUGE_VAL stattdessen auch in der definiert <math.h> Bibliothek.

HUGE_VAL sollte im C89/C90-Standard (ISO/IEC 9899:1990) verfügbar sein.

Verweise: http://en.cppreference.com/w/c/numeric/math/HUGE_VAL

Benutzeravatar von Clayton L
Clayton L

Es gibt einen tatsächlichen Weg, Unendlichkeit und negative Unendlichkeit zu erschaffen. Basierend auf dem IEEE 754-Standard, dem C89 folgt, ist unendlich als Gleitkommazahl definiert, die alle Nullen in der Mantisse (erste dreiundzwanzig Bits) und alle Einsen im Exponenten (nächste acht Bits) enthält. nan ist definiert als eine beliebige Zahl mit nur Einsen im Exponenten und allem außer Nullen in der Mantisse (weil das unendlich ist). Der schwierige Teil besteht darin, diese Nummer zu generieren, aber dies kann mit dem folgenden Code erreicht werden:

unsigned int p = 0x7F800000; // 0xFF << 23
unsigned int n = 0xFF800000; // 0xFF8 << 20
unsigned int pnan = 0x7F800001; // or anything above this up to 0x7FFFFFFF
unsigned int nnan = 0xFF800001; // or anything above this up to 0xFFFFFFFF

float positiveInfinity = *(float *)&p;
float negativeInfinity = *(float *)&n;
float positiveNaN = *(float *)&pnan;
float negativeNaN = *(float *)&nnan;

Allerdings einfach Casting an unsigned zu einem float würde dazu führen, dass der Compiler a erstellt float von gleichem Wert. Wir müssen also den Compiler zwingen, den Speicher als Float zu lesen, was uns das gewünschte Ergebnis liefert.

1409270cookie-checkWie generiert man NaN, -Infinity und +Infinity in ANSI C?

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

Privacy policy