Gleitkommatypen mit fester Größe

89

In den Headern stdint.h(C99), boost / cstdint.hpp und cstdint(C ++ 0x) gibt es unter anderem den Typ int32_t.

Gibt es ähnliche Gleitkommatypen mit fester Größe? So etwas wie float32_t?

Pietro
quelle
4
Warum brauchst du so etwas?
AraK
39
Sie benötigen so etwas, wenn Sie eine Datenstruktur mit einem Gleitkommawert haben und auch genau wissen möchten, wie groß diese ist.
Mob
5
@mobrule: Wenn Sie nur die Größe kennen müssen, verwenden Sie den sizeofOperator. Ein Typ wie dieser wäre nützlich, wenn ein Algorithmus eine bekannte spezifische Größe erfordert.
Stephen Canon
6
@ Stephen Canon - ja, wenn Sie die Größe garantieren möchten. Angenommen, eine Instanz Ihrer Datenstruktur passt in 64 Bit und kann als Wert an eine externe Bibliothek übergeben werden.
Mob
5
@StephenCanon Betrachten Sie eine plattformübergreifende Serialisierungsbibliothek. Wie kann sizeofdas Problem des konsistenten Marshalling und Unmarshalling von schwimmenden Typen gelöst werden?
Kyle Strand

Antworten:

47

In den C- oder C ++ - Standards gibt es derzeit nichts Vergleichbares. Tatsächlich gibt es nicht einmal eine Garantie dafür, dass floates sich überhaupt um ein binäres Gleitkommaformat handelt.

Einige Compiler garantieren, dass der floatTyp das 32-Bit-Binärformat IEEE-754 ist. Einige nicht. In Wirklichkeit floathandelt es sich tatsächlich um den singleTyp IEEE-754 auf den meisten nicht eingebetteten Plattformen, obwohl die üblichen Einschränkungen bei einigen Compilern gelten, die Ausdrücke in einem breiteren Format bewerten.

Es gibt eine Arbeitsgruppe, die das Hinzufügen von C-Sprachbindungen für die Revision von IEEE-754 von 2008 erörtert. Sie könnte in Betracht ziehen, die Hinzufügung eines solchen Typedef zu empfehlen. Wenn dies zu C hinzugefügt würde, würde der C ++ - Standard wahrscheinlich nachziehen ... irgendwann.

Stephen Canon
quelle
3
Unabhängig von IEEE-754 oder nicht, werden Endian-Portabilitätsprobleme immer noch nicht verhindert.
Mark B
1
@Pietro: Das Ändern der Sprache wirkt sich nicht auf Ihre Hardwarekompatibilität aus, sondern schließt nur die Kompatibilität einiger Hardware aus. Wie würde eine IEEE FP-Garantie die Portabilität verbessern?
Potatoswatter
1
@Potatoswatter: Dies würde Hardwareanbieter dazu ermutigen, kompatible Lösungen bereitzustellen. Wenn Teil a Standard C unterstützt, ohne Soft-Float-Bibliotheks-Hacks zu benötigen, und Teil b dies nicht tut, ist dies ein Marktvorteil für Teil a.
Stephen Canon
2
@ Potatoswatter: (Fast) niemand kümmert sich um die Geschwindigkeit der Hardware. Wir kümmern uns um die Geschwindigkeit der Software, die auf der Hardware ausgeführt wird. Software kann schneller sein, wenn die Hardware, auf der sie ausgeführt wird, den Standards entspricht und die Software nicht 15 verschiedene Sonderfälle erkennen und patchen muss, je nachdem, auf welcher Plattform sie ausgeführt wird.
Stephen Canon
8
Wie um alles in der Welt würden Sie eine bessere Portabilität erzielen, wenn Sie verhindern würden, dass Ihr Code auf einer Reihe von Nischenarchitekturen kompiliert wird? Entweder verlassen Sie sich darauf, dass Floats IEEE sind. In diesem Fall wird Ihr Code bereits auf jeder IEEE-kompatiblen Implementierung und sonst nichts ausgeführt, oder Sie tun dies nicht. In diesem Fall wird Ihr Code auf einer größeren Anzahl von Systemen ausgeführt. Wenn C ++ die IEEE-Konformität garantieren würde, würde Ihr Code nicht auf magische Weise portabler werden. Sie würden nur ausschließen, dass er jemals auf diesen nicht konformen Architekturen ausgeführt werden könnte. Ihre Logik ist völlig rückwärts.
Jalf
29

Wenn Sie wissen möchten, ob floates sich um den IEEE 32-Bit-Typ handelt, überprüfen Sie std::numeric_limits<float>::is_iec559. Es ist eine Konstante zur Kompilierungszeit, keine Funktion.

Wenn Sie kugelsicherer sein möchten, std::numeric_limits<float>::digitsstellen Sie außerdem sicher, dass sie nicht den IEEE-Standard mit doppelter Genauigkeit für verwenden float. Es sollte 24 sein.

Wenn es darum geht, long doubleist es wichtiger zu überprüfen, digitsda es einige IEEE-Formate gibt, die vernünftigerweise sein könnten: 128 Bit (Ziffern = 113) oder 80 Bit (Ziffern = 64).

Es wäre nicht praktisch, dies float32_tzu tun, da Sie normalerweise Gleitkomma-Hardware verwenden möchten, sofern verfügbar, und nicht auf eine Software-Implementierung zurückgreifen möchten.

Kartoffelklatsche
quelle
Das long doubleFormat unter OS X (sowohl 32-Bit- als auch 64-Bit-Intel) ist genau das doppelt erweiterte IEEE-754-Format, das in Little-Endian-Reihenfolge gespeichert ist. Daran ist überhaupt nichts Ungewöhnliches. Die Bytes 0-7 enthalten das Signifikantenfeld und die Bytes 8 und 9 enthalten die Exponenten- und Vorzeichenfelder.
Stephen Canon
@ Stephen: das sind gute Nachrichten: v). Stimmt das mit den Zahlen überein, die ich gepostet habe?
Potatoswatter
1
Denken Sie daran, dass Double Extended (im Gegensatz zu den anderen 754-Formaten) ein explizit führendes Signifikanzbit hat, also 5.0Lein Signifikand von a000000000000000. Sein unverzerrter Exponent ist +2 und die doppelt erweiterte Exponentenvorspannung ist 3fff, so dass der vorgespannte Exponent für 5,0 l ist 4001. Das tatsächliche Bytemuster, wenn es in Little-Endian-Reihenfolge gespeichert wird 00 00 00 00 00 00 00 a0 01 40, ist , und wenn Sie dies als zwei Little-Endian-64-Bit-Ganzzahlen betrachten, sehen Sie genau, was Sie beobachtet haben.
Stephen Canon
(*) doppelt erweitert, wie von Intel in Hardware implementiert, das heißt. Das doppelt erweiterte Format ist nicht so festgelegt wie die beiden anderen Grundformate von IEEE-754 (1985).
Stephen Canon
@ Stephen: Ich bin mir ziemlich sicher, dass 4001in Little-Endian 01 40 00 00 ...Wenn nichts anderes steht, steht das niedrigstwertige Byte an erster Stelle. Ich erwarte, dass die Sequenz a0 01 40irgendwo in der Zahl erscheint (wenn sie nur eine Rotation durchgeführt haben), aber ich glaube nicht, dass Sie erklärt haben, warum a0und 01 40in völlig getrennten Hälften sind.
Potatoswatter
18

Wenn Sie der Meinung sind, dass Typedefs wie float32_t und float64_t aus irgendeinem Grund unpraktisch sind, müssen Sie sich zu sehr an Ihr bekanntes Betriebssystem, den Compiler, gewöhnt haben, um nicht außerhalb Ihres kleinen Nestes schauen zu können.

Es gibt Hardware, die nativ 32-Bit-IEEE-Gleitkommaoperationen ausführt, und andere, die 64-Bit ausführen. Manchmal müssen solche Systeme sogar miteinander kommunizieren. In diesem Fall ist es äußerst wichtig zu wissen, ob ein Double auf jeder Plattform 32-Bit oder 64-Bit ist. Wenn die 32-Bit-Plattform übermäßige Berechnungen auf der Basis der 64-Bit-Werte der anderen Plattform durchführen würde, möchten wir je nach Timing- und Geschwindigkeitsanforderungen möglicherweise eine geringere Genauigkeit erzielen.

Ich persönlich fühle mich unwohl mit Floats und Doubles, es sei denn, ich weiß genau, wie viele Bits sich auf meiner Plattform befinden. Umso mehr, wenn ich diese über einen Kommunikationskanal auf eine andere Plattform übertragen möchte.

EmbeddedCoder
quelle
"Ich persönlich fühle mich unwohl mit Floats und Doubles, wenn ich nicht genau weiß, wie viele Bits sich auf meiner Plattform befinden. Dies gilt umso mehr, wenn ich diese über einen Kommunikationskanal auf eine andere Plattform übertragen möchte." - Sie meinen, Sie verwenden Textdateiformate? Bei diesen gibt es den Nachteil der Dateigröße: Ein 32-Float benötigt 4 Bytes; Diese in Textform können nur eine vierstellige Zahl darstellen ...
Pietro
3

Derzeit wird vorgeschlagen, die folgenden Typen in die Sprache aufzunehmen:

decimal32
decimal64
decimal128

die eines Tages zugänglich sein kann durch #include <decimal>.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3871.html

Trevor Hickey
quelle
3
Zugegeben, die Dezimaltypen sind nicht die Gleitkommatypen IEEE 754.
Mike DeSimone