Umwandlung von JAVA double in C++ double



  • Das Problem mit XML oder JSON wäre ein erhöhter overhead und bei meinem Problem geht es darum teilweise sechzig mal die Sekunde große Datenmengen zu übertragen.

    Ich mache das mit einem DataoutputStream:

    DataOutputStream outputStream;
    ...
    Translation tr = data.get(i).read();
    
    outputStream.writeInt(i);
    outputStream.writeInt(data.get(i).getParentID());
    outputStream.writeDouble(tr.getX());
    outputStream.writeDouble(tr.getY());
    outputStream.writeDouble(tr.getZ());
    outputStream.writeDouble(tr.getA());
    outputStream.writeDouble(tr.getB());
    outputStream.writeDouble(tr.getC());
    
    ...
    outputStream.flush();
    


  • Der DataOutputStream dreht die Bytes um, er schreibt in Big Endian. Siehe https://en.wikipedia.org/wiki/Endianness. Wie floats und doubles geschrieben werden, kannst du vermutlich der Dokumentation entnehmen.



  • d.h. deine "int32 bitsToInt(uint8* bytes)" ist der total falsche und unnötige Ansatz

    du musst nur high und low bytes verdrehen, bei float und double koennte es genau so sein



  • Für Integer sollte ntohl die Bytes richtig drehen.



  • Danke für die Antworten, dann werde ich erstmal versuchen das auf der JAVA Seite mit einem OutpuStrem zu beheben.



  • Also ich habe das jetzt auf der JAVA Seite erfolgreich gelöst:
    Den DataOutputStream kann man behalten, wenn man davor die bytes umdreht. Bei Integern geht das mit

    Integer.reverseBytes(int x)
    

    . Bei double wird es schon ein bisschen umständlicher. Da habe ich mir eine kleine Hilfsfunktion geschrieben:

    public static double reverse(double in){
            return Double.longBitsToDouble(Long.reverseBytes(Double.doubleToLongBits(in)));
        }
    


  • du könntest ja den float Wert aufteilen auf: Vorzeichen, Mantisse, Exponent.
    Die drei Werte speicherst du getrennt (z.B. als int oder als string) und lädst auch wieder getrennt rein - dann musst du nicht auf Bitebene rumbasteln.



  • mnmnbmn schrieb:

    du könntest ja den float Wert aufteilen auf: Vorzeichen, Mantisse, Exponent ..... dann musst du nicht auf Bitebene rumbasteln.

    Ah ja ... und wie teilt man das auf, ohne auf Bitebene rumzubasteln?



  • lonol15 schrieb:

    public static double reverse(double in){
            return Double.longBitsToDouble(Long.reverseBytes(Double.doubleToLongBits(in)));
        }
    

    Keine gute Idee.
    Was wenn die falsche Byte-Reihenfolge einen signaling NaN darstellt?



  • Belli schrieb:

    mnmnbmn schrieb:

    du könntest ja den float Wert aufteilen auf: Vorzeichen, Mantisse, Exponent ..... dann musst du nicht auf Bitebene rumbasteln.

    Ah ja ... und wie teilt man das auf, ohne auf Bitebene rumzubasteln?

    z.B. mit frexp & Co.
    http://www.cplusplus.com/reference/cmath/frexp/

    Die Mantisse bekommt man dabei wieder als double .
    Macht aber nix, da man dann weiss dass die sich irgendwo im Bereich [0.5 ... 1) bewegt.
    Bzw. wenn negativ dann halt (-1 ... -0.5].

    D.h. man kann erstmal das Vorzeichen notieren und rausrechnen und dann einfach so lange
    * verdoppeln
    * wenn >= 1 dann 1 abziehen
    * wiederholen
    bis der Wert 0 ist.
    Bzw. einfach N mal wiederholen (mit N = grösste zu erwartende Mantissenbreite).
    Und bei jedem Durchlauf ne 1 bzw. 0 notieren, je nachdem ob man 1 abgezogen hat oder nicht.

    Und den Exponenten bekommt man von frexp ja sowieso schon als Integer.

    Alles ohne Bitfummelei.
    Die umgekehrte Richtung sollte trivial sein.

    Dann fehlen bloss noch die Spezialwerte (NaNs, INFs, ...).
    Vorzeichen für 0 und die Spezielwerte kann man mit copysign abfragen (und erzeugen).
    http://en.cppreference.com/w/cpp/numeric/math/copysign




Anmelden zum Antworten