Fließkommazahlen mit fester Breite in C/C++

Lesezeit: 6 Minuten

Benutzer-Avatar
Imagist

int ist normalerweise 32 Bit, aber im Standard int Eine konstante Breite ist nicht garantiert. Also, wenn wir ein 32-Bit wollen int wir beinhalten stdint.h und verwenden int32_t.

Gibt es dafür ein Äquivalent für Schwimmer? Mir ist klar, dass es mit Floats etwas komplizierter ist, da sie nicht auf homogene Weise gespeichert werden, dh Vorzeichen, Exponent, Signifikand. Ich will nur ein double das wird garantiert in 64 Bit mit 1 Vorzeichenbit, 10 Bit Exponent und 52/53 Bit Signifikand gespeichert (abhängig davon, ob Sie das versteckte Bit zählen).

  • Typischerweise wird die Anzahl der Bits für ein int benötigt, da es eine Art von Objekt-Flags codiert. Warum brauchen Sie Garantien für die Genauigkeit Ihrer Schwimmer? In den meisten Fällen habe ich gesehen, dass Menschen dazu neigen, die Bedeutung der Größe von Zufallsvariablen zu überschätzen. Oft ist es besser, die Standardwortgröße der Maschine zu verwenden, als zu versuchen, 3 Bytes Speicher herauszuquetschen oder willkürlich 32-Bit-Werte zu verwenden.

    – Andrew Chosravian

    26. August 2009 um 1:09 Uhr

  • @Andrew-Khosravian Ich schreibe eine Skriptsprache und möchte meinen Benutzern Schriftgrößengarantien geben können. Das macht Code, der in meiner Skriptsprache geschrieben wurde, portabler.

    – Imagist

    26. August 2009 um 1:35 Uhr

  • Portabilität ist in Ordnung, aber irgendwo müssen Sie die Grenze ziehen – schließlich erwarten Sie wahrscheinlich nicht, dass Ihre Skriptsprache auf einem PDP-11 läuft. Sehr wenige Plattformen unterstützen IEEE 754 nicht, und wenn das unterstützt wird, dann ist es eine vernünftige Annahme, dass Double tatsächlich 64 Bit ist (da es sich um eine doppelt-Präzisions-Gleitkommawert) – und für den Fall, dass dies nicht der Fall ist, bauen Sie eine Plausibilitätsprüfung ein, damit Benutzer dies melden können und Sie diese Plattform separat behandeln können. Wenn die Plattform IEEE 754 nicht unterstützt, erhalten Sie diese Darstellung sowieso nicht, es sei denn, Sie implementieren sie selbst.

    – Michael Madson

    26. August 2009 um 2:50 Uhr

  • int ist es garantiert wenigstens 16 Bit und long int mindestens 32 Bit (obwohl es tatsächlich in Bezug auf den Bereich der darstellbaren Werte definiert ist) – wenn Sie also eine Variable wollen, die jede ganze Zahl von -2147483647 bis 2147483647 speichern kann, long int ist gut.

    – Café

    26. August 2009 um 7:16 Uhr

  • @caf Und wenn ich eine Variable will, die speichern kann exakt 32 Bit plattformübergreifend? int32_t.

    – Imagist

    26. August 2009 um 15:53 ​​Uhr

Benutzer-Avatar
Michael Madson

Entsprechend der aktuelle C99-Standardentwurf, Anhang F, das sollte doppelt sein. Dies setzt natürlich voraus, dass Ihre Compiler diesen Teil des Standards erfüllen.

Für C++ habe ich den 0x-Entwurf und einen Entwurf für die Version 1998 des Standards überprüft, aber keiner scheint irgendetwas über die Darstellung wie den Teil des C99-Standards zu spezifizieren, abgesehen von einem bool in numeric_limits, der diesen IEEE 754/IEC 559 angibt wird auf dieser Plattform verwendet, wie Josh Kelley erwähnt.

Sehr wenige Plattformen unterstützen IEEE 754 jedoch nicht – es lohnt sich im Allgemeinen nicht, ein anderes Gleitkommaformat zu entwickeln, da IEEE 754 gut definiert ist und recht gut funktioniert – und wenn das unterstützt wird, dann ist es eine vernünftige Annahme, dass es doppelt ist ist in der Tat 64 Bit (IEEE 754-1985 nennt dieses Format immerhin Double-Precision, also macht es Sinn).

Für den Fall, dass doppelt keine doppelte Genauigkeit ist, bauen Sie eine Plausibilitätsprüfung ein, damit Benutzer dies melden können und Sie diese Plattform separat verwalten können. Wenn die Plattform IEEE 754 nicht unterstützt, erhalten Sie diese Darstellung sowieso nicht, es sei denn, Sie implementieren sie selbst.

  • Ich stimme nicht zu, dass IEEE 754 ganz gut funktioniert, es ist gut verankert, so dass man nicht viel gegen ot tun kann. Ich stimme zu, dass das, was Sie wollen, doppelt ist und Sie eine Plausibilitätsprüfung hinzufügen möchten, die fehlschlägt, wenn jemand einen Compiler findet, der ein doppeltes mit der falschen Größe hat.

    – Oldtimer

    28. August 2009 um 20:03 Uhr

  • @dwelch: Ich sage nicht, dass es keine Probleme gibt oder dass es immer die beste Wahl ist, aber es sei denn, Sie müssen extrem präzise sein oder haben anderweitig sehr spezielle Bedürfnisse, wenn es um Gleitkommazahlen geht , IEEE 754 neigt dazu, den Zweck zu erfüllen, ohne außergewöhnlich langsam zu sein.

    – Michael Madson

    28. August 2009 um 21:51 Uhr

  • Einverstanden, das Format ist in Ordnung, es sind alle Rundungs- und Ausnahmeregeln, die das Problem darstellen, sodass nur wenige oder gar keine Implementierungen korrekt sind. Etwas zwischen IEEE 754 und dem TI DSP-Format wäre eine Idee, da das TI DSP-Format keine Funktionen hat (aber superschnell und einfach zu implementieren und richtig zu machen ist).

    – Oldtimer

    29. August 2009 um 16:12 Uhr

Obwohl ich keinen Typ kenne, der eine bestimmte Größe und ein bestimmtes Format garantiert, haben Sie in C++ einige Optionen. Du kannst den … benutzen <limits> Header und seine std::numeric_limits Klassenvorlage, um die Größe eines bestimmten Typs herauszufinden, std::numeric_limits::digits gibt Ihnen die Anzahl der Bits in der Mantisse an, und std::numeric_limits::is_iec559 sollte Ihnen sagen, ob der Typ dem IEEE-Format folgt. (Beispielcode, der IEEE-Zahlen auf Bitebene manipuliert, finden Sie in der FloatingPoint-Klassenvorlage in Google Test’s gtest-intern.h.)

Das andere Problem ist die Darstellung von Gleitkommazahlen. Dies basiert normalerweise auf der Hardware, auf der Sie ausgeführt werden (aber nicht immer). Die meisten Systeme verwenden IEEE 754-Gleitkommastandards, aber andere können auch ihre eigenen Standards haben (ein Beispiel wäre ein VAX-Computer).

Wikipedia-Erklärung zu IEEE 754 http://en.wikipedia.org/wiki/IEEE_754-2008

Mir ist keine Variation in Float/Double bekannt. Float ist seit Ewigkeiten 32 Bit und Double 64 Bit. Gleitkomma-Semantik ist ziemlich kompliziert, aber es gibt Konstanten darin

#include <limits>

boost.numeric.bounds ist eine einfachere Schnittstelle, wenn Sie nicht alles in std::numeric_limits benötigen

Benutzer-Avatar
Steve K

Auch das ist leider nicht garantiert. Sie müssen überprüfen numeric_limits< T > in
<limits>.

Andererseits habe ich noch nie von einer Implementierung gehört, bei der ein Double nicht 64 Bit lang war. Wenn Sie nur vermuten wollten, würden Sie wahrscheinlich damit durchkommen.

Eines der größten Probleme mit dieser Art von „Typen mit fester Breite“ ist, dass es so leicht ist, etwas falsch zu machen. Sie wollten wahrscheinlich keine 32-Bit-Ganzzahl. Was ist der Punkt? Was Sie wollten, ist ein Integer-Typ, der mindestens 1 >> 31 speichern kann. Das ist long int. Du brauchst nicht einmal <stdint.h> dafür.

Ebenso kann Ihre Skriptsprache einen FP-Typ implementieren, der so lange funktioniert wie das zugrunde liegende C++ float ist wenigstens 32 Bit. Beachten Sie, dass dies Ihnen immer noch kein genaues Verhalten gibt. Ich bin mir ziemlich sicher, dass C++ das nicht garantiert -1.0/-3.0==1.0/3.0

1366700cookie-checkFließkommazahlen mit fester Breite in C/C++

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

Privacy policy