Portabilität der binären Serialisierung von double - /float-Typ in C++
Den C++ - standard behandelt nicht die zugrunde liegenden layout von float-und double-Typen, nur der Bereich der Werte, die Sie repräsentieren sollten. (Dies gilt auch für signed-Typen, ist es zwei s Kompliment oder etwas anderes)
Meine Frage ist: Was sind die Methoden zum serialisieren/Deserialisieren von POD-Typen wie double und float in portabler Art und Weise? Im moment scheint es der einzige Weg, dies zu tun ist, um den dargestellten Wert buchstäblich(wie in "123.456"), Die ieee754-layout für die Doppel ist nicht standard auf allen Architekturen.
- Wenn Sie brauchen, file-storage, im HDF5 oder NetCDF sehr helfen.
- Gute Frage.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brian "Beej Jorgensen" Halle, gibt in seinem Guide to Network Programming code zu packen
float
(resp.double
) zuuint32_t
(resp.uint64_t
) in der Lage sein, um sicher zu übertragen es über das Netzwerk zwischen zwei Maschinen, die können nicht beide Stimmen auf Ihre Darstellung. Es hat einige Einschränkungen, vor allem ist es nicht support-NaN und infinity.Hier ist seine Verpackung-Funktion:
frexp
-basierten Ansatz werden durchweg schneller als die wiederholte floating point division / Multiplikation?frexp
gibt Sieexp
undfnorm
in einem einzigen Aufruf. Beachten Sie IEEE-754 double 11 bits Wert des Exponenten, so konnte man die Aufteilung / multipying von 2 mehrere hundert mal.frexp
-basierten Ansatz so Aussehen wie in dieser situation? Ich habe Mühe mit floating-point-Serialisierung jetzt, und während diefrexp
Ansatz scheint interessant, ich kann nicht herausfinden, wie konvertiert man die Mantisse (das ist zwischen 0,5 und 1) zu der Reihe von bits repräsentieren die Mantisse in IEEE float oder double. Gibt es eine effiziente und portable Weg, das zu tun?significand = fnorm * ((1LL<<significandbits) + 0.5f);
dies funktioniert?Was ist falsch mit einem für Menschen lesbaren format.
Es hat ein paar Vorteile gegenüber Binär:
(wie können Sie den Benutzer auffordern, zu betrachten, es in Ihrem Lieblings-editor auch word)
(oder passen Sie die Dateien manuell in Fehler-Situationen)
Nachteil:
Wenn dies ein echtes problem, Sie können immer zip.
Hinweis: ein binäres format, eventuell muss normalisiert werden (siehe
htonl()
)Ausgabe ein double mit voller Genauigkeit:
OK. Ich bin nicht überzeugt, dass ist genau, präzise. Es kann verlieren an Präzision.
numeric_limits
. Leider ist es immer noch Präzision Verlust mit der Nutzung dieser für einige Ausnahmefälle. Siehe codepad.org/WbACWihl17.3
- das ist es.). Vergleichen Sie die Genauigkeit und den Wertebereich, den Sie bekommen können, mit den gleichen 4 Byte-ieee-float-format.Werfen Sie einen Blick auf die (alte) gtypes.h-Datei-Implementierung in glib-2 - es beinhaltet folgende Leistungen:
glib link
Schreiben Sie einfach die binary IEEE754 Darstellung auf der Festplatte, und dokumentieren Ihre storage-format (zusammen mit endianness). Dann ist es bis zur Umsetzung zu konvertieren, das in seiner internen Darstellung, wenn nötig.
Erstellen Sie eine entsprechende serializer/de-serializer-Schnittstelle für das schreiben/Lesen.
Kann das interface dann haben mehrere Implementierungen und Sie können testen Sie Ihre Möglichkeiten.
Wie gesagt, offensichtliche Möglichkeiten wären:
Denken Sie daran - sobald Sie diese Ebene ist, können Sie beginnen immer mit IEEE754 wenn Sie nur die Plattformen, die dieses format verwenden intern. Auf diese Weise werden Sie den zusätzlichen Aufwand nur, wenn Sie brauchen, um Unterstützung für eine andere Plattform! Nicht tun Arbeit, die Sie nicht haben, um.
Sollten Sie konvertieren Sie Sie in ein format, das Sie immer in der Lage sein zu verwenden, um zu erstellen Ihre floats/doubles.
Dies könnte die Verwendung eines string-Darstellung oder, wenn Sie etwas brauchen, das nimmt weniger Platz, stellen Ihre Nummer im ieee754 (oder jedes andere format, das Sie wählen) und dann analysieren es, als würden Sie mit einer Schnur.
Ich denke, dass die Antwort "hängt" sich auf, was Sie für Ihre bestimmte Anwendung und es ist perfomance-Profil ist.
Lassen Sie uns sagen, Sie haben ein low-latency Marktdaten-Umgebung, dann mit strings ist ehrlich gesagt bescheuert. Wenn die Informationen, die Sie vermitteln, ist Preise, dann verdoppelt sich (und binäre Darstellung von Ihnen) sind wirklich schwierig, mit zu arbeiten. Wo, wie, wenn Sie nicht wirklich über Leistung, und was Sie wollen, ist die Sichtbarkeit (Speicherung, übertragung), Saiten sind ein Idealer Kandidat.
Ich würde eigentlich entscheiden Sie sich für Integrale Mantisse/exponent Darstellung von floats/doubles - d.h. bei der frühesten Gelegenheit, umwandeln der float/double zu einem paar von ganzen zahlen und dann übertragen. Sie müssen dann nur noch Gedanken über die Portabilität von Integer-zahlen und auch diverse Routinen (wie die
hton()
Routinen zu behandeln Konvertierungen für Sie). Auch speichern alles in Ihrer weitesten verbreitete Plattform, das endian Typ (zum Beispiel, wenn Sie nur mit linux, was ist dann der Punkt der Speicherung von Sachen in big-endian?)atoi()
,scanf()
,sprintf()
, was vergleichsweise langsam...Den SQLite4 verwendet ein neues format zur Speicherung von doubles und floats
Quellen:
https://sqlite.org/src4/doc/trunk/www/design.wiki
https://sqlite.org/src4/doc/trunk/www/decimal.wiki
Fand diesen alten thread. Eine Lösung, die löst ein fairer deal der Fälle fehlt - fixed point, vorbei an ganzen zahlen, die mit einem bekannten Skalierungsfaktor mithilfe der integrierten wirft in jedem Ende. Also, Sie müssen nicht die Mühe mit den zugrunde liegenden floating-point-Darstellung überhaupt nicht.
Gibt es natürlich auch Nachteile. Diese Lösung setzt Voraus, Sie kann eine Feste Skalierung und immer noch sowohl die Bandbreite und Auflösung benötigt, für die bestimmte Anwendung. Außerdem konvertieren Sie von Ihrem floating-point zu fixed-point bei der Serialisierung Ende und wieder zurück konvertieren bei der Deserialisierung, die Einführung von zwei Rundungsfehler.
Doch im Laufe der Jahre, die ich gefunden habe Fixpunkt ist genug für meine Bedürfnisse in fast allen Fällen, und es ist Recht schnell zu.
Ein typischer Fall für fester Punkt wäre Kommunikationsprotokollen für embedded-Systeme oder andere Geräte.