2010-11-10 16 views
8

Angenommen, ich habe eine API, die es mir nur erlaubt, Floats oder Float-Arrays zu speichern. Allerdings möchte ich hier ganzzahlige Werte speichern.Speichern von Ints als Gleitkommazahlen

Ich verstehe (grob), dass ich ziemlich gut bin mit einem Straight Cast bis zu 2^23, aber was, wenn ich höher gehen will? Gibt es irgendeine Möglichkeit, dass ich mehr von den 32 Bits eines Floats ausnutzen kann und sicher sein werde, dass ich dieselbe Nummer zurückbekomme?


Zur Klarstellung:

ich mit Pixars PRMan einige Operationen auf Punktwolken mache (also RenderMan.). Ich kann in C oder C++ schreiben, indem ich mit der vorkompilierten Punktwolken-API verlinke. PRMan muss zu keinem Zeitpunkt diese Ints verwenden, die ich speichere; Ich brauche es nur, um es mir intakt zu übergeben, nachdem ich andere Daten an den Punkten bearbeitet habe.

+2

In welcher Sprache sprechen wir? –

+0

Ich habe ein wenig geklärt. =] –

+0

Es ist auch wichtig zu wissen, auf welcher Plattform Sie wissen, wie Floats implementiert sind. Aber es ist wahrscheinlich eine * wirklich * sichere Wette, dass Sie IEEE Floats verwenden. –

Antwort

8

Fragwürdige:

In C, können Sie das folgende tun, die potenziell unsicher ist (wegen der strengen-Aliasing-Regeln):

int i = XXX; 
float f; 
*(int *)&f = i; 

und das beruht auf der Annahme, dass sizeof(int) == sizeof(float).

Weniger fragwürdig:

sicherer, aber mehr langatmig, ist die folgende:

int i = XXX; 
float f; 
memcpy(&f, &i, sizeof(int)); 

Dies setzt weiterhin Datentyp Größen auf übereinstimmen. Jedoch machen beide der oben genannten die Annahme, dass die Interna der Bibliothek, die Sie verwenden, nichts überhaupt zu den Daten tun werden. Zum Beispiel wird es keine Sonderbehandlung für NaN haben, oder +/- unendlich usw.

Sicher:

Entlang einer ganz anderen Gedankengang, wenn Sie glücklich sind zwei zu verschwenden

int i = XXX; 
float f[2] = { (i & 0xFFFF), ((unsigned)i >> 16 }; 

Dieses letzt man sicher ist (außer ein paar ziemlich vernünftigen Annahmen über die Größe von Schwimmern und ints): pro int schwimmt, könnte man so etwas tun.

+1

Würden Sie nicht einfach i >> 16 für f [1] verwenden? – MSN

+0

Einige Float-Bitmuster sind reserviert und können nicht verwendet werden. Wenn Sie also in der Lage sind, sie über eine Float-Variable im Speicher zu schreiben, können Sie den Speichercontainer auf unvorhersehbare Weise beschädigen, wenn Sie sie an eine bestimmte Speicherform übergeben. Wir haben keine Informationen über den Speicher und können daher nicht garantieren, dass dies funktioniert. –

+0

@Martin: Ja, ich habe in meiner Antwort darauf hingewiesen. –

3

Im Mantissenfeld können Sie 23 Bits speichern. Das Exponentenfeld lässt Sie fast 8 Bits speichern, es ist 8 Bits breit mit einigen reservierten Werten. Und es gibt ein Vorzeichen.

Wenn Sie die reservierten Werte im Exponenten vermeiden, können Sie immer noch 31 Bits Ihrer Wahl speichern.

Sie können frexp und ldexp nützlich finden.

0

Alle hier angegebenen Antworten gehen davon aus, dass Sie nur die Bytes verwenden möchten, die für den Float-Speicher reserviert sind, als Speicherort für einen int. Sie werden Ihnen nicht erlauben, Arithmetik für die int-encoded-in-float-Werte auszuführen. Wenn Sie wollen, dass Arithmetik funktioniert, stecken Sie mit 24.99 Bits fest (dh einem Bereich von - (2^24-1) bis (2^24-1); ich halte das Vorzeichenbit für 0.99 Bits anstatt für 1 Bit, weil Sie kann nicht den niedrigstmöglichen Wert mit der Vorzeichen-/Betragsdarstellung von float speichern) und eine spärliche Menge größerer Werte (z. B.jedes 32-Bit-Ganzzahl-Vielfache von 256 ist in float darstellbar).

+0

Das sollten 24 Bit sein, oder? Single-Precision hat 1 Vorzeichenbit und 23 Mantissenbits. –