2010-03-19 7 views
5

Ich muss eine IEEE 754-1985 double (64-bit) Fließkommazahl in einer von Menschen lesbaren Textform darstellen, mit der Bedingung, dass die Textform wieder hinein geparst werden kann genau die gleiche (bitweise) Nummer.Exakte textuelle Darstellung eines IEEE "double"

Ist das möglich/praktisch, ohne nur die rohen Bytes zu drucken? Wenn ja, würde Code, um dies zu tun, sehr geschätzt werden.

+1

Sprache zählt. In welcher Sprache arbeiten Sie? Es ist irgendwie unmöglich, Code mit keiner spezifischen Sprache bereitzustellen, die in dem Problem erwähnt wird. –

+0

Ich habe die Sprache (D) nicht erwähnt, weil sie vergleichsweise selten ist, deshalb plante ich, einen in irgendeiner Sprache geschriebenen Algorithmus in D zu schreiben. –

+0

Wie wäre es mit NaN, -0.0, inf, -inf? Die aktuelle Antwort scheint diese nicht zu berücksichtigen. –

Antwort

11

Beste Option: Verwenden Sie den C99 hexadezimal Gleitpunktformat:

printf("%a", someDouble); 

Strings auf diese Weise hergestellt wird, kann zurück in double mit der C99 strtod() Funktion, und auch mit den scanf() Funktionen umgewandelt werden. Mehrere andere Sprachen unterstützen dieses Format ebenfalls. Einige Beispiele:

decimal number %a format  meaning 
-------------------------------------------- 
2.0    0x1.0p1  1.0 * 2^1 
0.75    0x1.8p-1  1.5 * 2^-1 

Das Hexadezimal-Format hat den Vorteil, dass alle Darstellungen sind genaue. Wenn Sie also den String wieder in Gleitkomma umwandeln, erhalten Sie immer die ursprüngliche Zahl, selbst wenn jemand den Rundungsmodus ändert, in dem die Konvertierung durchgeführt wird. Dies gilt nicht für ungenaue Formate.

Wenn Sie das hexadezimale Format aus welchem ​​Grund auch immer nicht verwenden möchten und davon ausgehen, dass der Rundungsmodus immer rund ist (Standard), dann können Sie Ihre Daten als Dezimalzahlen formatieren mit mindestens 17 signifikanten Ziffern. Wenn Sie eine korrekt gerundete Konvertierungsroutine haben (die meisten - nicht alle - Plattformen tun dies), garantiert dies, dass Sie einen Rundlauf von Double zu String und zurück ohne Genauigkeitsverlust durchführen können.

+0

Vielen Dank für die sehr detaillierte Antwort! –

1

Ja, es kann getan werden, obwohl die Implementierung von der Sprache abhängt. Die Grundidee ist einfach, es mit ausreichender Genauigkeit auszudrucken.

Beachten Sie, dass die umgekehrte nicht True ist: einige Zahlen, die genau in Dezimal einfach dargestellt werden können einfach nicht in Binär dargestellt werden.

2

Die .NET-Framework hat ein Round-Trip-Format für diesen:

string formatted = myDouble.ToString("r"); 

Aus der Dokumentation:

Der Round-Trip-Spezifizierer garantiert, dass ein numerischer Wert in einen String umgewandelt wird wieder in den gleichen numerischen Wert geparst. Wenn ein numerischer Wert mit diesem Spezifizierer formatiert wird, wird er zuerst mit dem allgemeinen Format mit 15 Genauigkeitsspaces für einen Double und 7 Präzisionsräume für einen Single getestet. Wenn der Wert erfolgreich auf den gleichen numerischen Wert zurückgesetzt wurde, wird mit dem allgemeinen Formatbezeichner formatiert. Wenn jedoch der Wert nicht erfolgreich auf den gleichen numerischen Wert analysiert wird, wird der Wert mit 17 Ziffern Genauigkeit für eine doppelte und 9 Ziffern von Genauigkeit für eine Single formatiert.

Diese Methode könnte natürlich in fast jeder Sprache neu erstellt werden.

5

klingen wie Sie Burger's algorithm (PDF) wollen:

Im Freiformat-Modus erzeugt der Algorithmus die kürzeste richtig gerundet Ausgabezeichenfolge, die die gleiche Anzahl an umwandelt, wenn wieder in unabhängig davon, wie die lesen Leser bricht Krawatten beim Runden.

Sample source code (in C und Scheme) ist ebenfalls verfügbar.

Dies ist der in Python 3.x verwendete Algorithmus, um sicherzustellen, dass float s ohne Verlust der Genauigkeit in Zeichenfolgen und zurück konvertiert werden können. In Python 2.x wurden float s immer mit 17 signifikanten Stellen dargestellt, weil:

repr(float) 17 signifikante Stellen erzeugt, weil es stellt sich heraus, dass genug ist (auf den meisten Maschinen), so dass eval(repr(x)) == x genau für alle endlichen Schwimmer x, aber Das Runden auf 16 Ziffern ist nicht genug, um dies zu bestätigen. (Quelle: http://docs.python.org/tutorial/floatingpoint.html)

Verwandte Themen