2016-07-16 6 views
0

Ich muss einen Koordinatenwert, der ein float ist, in ein protobuf-Objekt konvertieren, um es an einen Server zu senden Problem ist, dass ich es in ein fixed64 Objekt konvertieren muss, das ist ein 64bit lang und Javascript unterstützt keine Zahlen so lange.Umwandlung eines Koordinatenwertes in ein fixed64 protobuf-Objekt

Ich verwende this Bibliothek, um meine Protobuf-Puffer zu erstellen. Ich habe eine funktionierende Python-Schnipsel gefunden

def f2i(float): 
    return struct.unpack('<Q', struct.pack('<d', float))[0] 

Dies verwendet die Struktur Bibliothek das gleiche Problem anpackt, und wandelt im Wesentlichen den Schwimmer in binäre, und dann auf eine lange zurück. Ich brauche die gleiche Ausgabe

So 51,366805 werden 4632426052430037296

verlieren würde ein wenig Präzision zu bekommen, ist nicht das größte Problem, ich muss nur

Antwort

1

den Wert konvertieren Wie Sie erwähnt haben, JS doesn Es werden keine 64-Bit-Ganzzahlen unterstützt, so dass Sie nicht den gleichen-Ausgang erhalten können. Der nächste Wert, den Sie erhalten können, wären zwei 32-Bit-Ganzzahlen, die die gleiche 64-Bit-Ganzzahl darstellen. Je nachdem, welche Art von Eingabe Ihre Protobuf-Bibliothek erwartet, kann oder kann sie nicht funktionieren.

Ich würde vorschlagen, sich die Funktion toFloat64() in der angenommenen Antwort für this question anzusehen.

Unten finden Sie eine leicht vereinfachte Version:

function toFloat64(value) { 
    var hiWord = 0, loWord = 0; 

    if (value <= -0.0) { 
     hiWord = 0x80000000; 
     value = -value; 
    } 

    var exponent = Math.floor(Math.log(value)/Math.log(2)); 
    var significand = Math.floor((value/Math.pow(2, exponent)) * Math.pow(2, 52)); 

    loWord = significand & 0xFFFFFFFF; 
    significand /= Math.pow(2, 32); 

    exponent += 1023; 
    if (exponent >= 0x7FF) { 
     exponent = 0x7FF; 
     significand = 0; 
    } else if (exponent < 0) exponent = 0; 

    hiWord = hiWord | (exponent << 20); 
    hiWord = hiWord | (significand & ~(-1 << 20)); 

    return [hiWord, loWord]; 
} 

ist es einen Versuch geben lassen:

var res = toFloat64(51.366805), 
    hexHi = ('0000000' + res[0].toString(16)).substr(-8, 8), 
    hexLo = ('0000000' + res[1].toString(16)).substr(-8, 8); 

console.log('32-bit high word = 0x' + hexHi); 
console.log('32-bit low word = 0x' + hexLo); 
console.log('64-bit result = 0x' + hexHi + hexLo); 

Ausgang:

32-bit high word = 0x4049aef3 
32-bit low word = 0x775b8130 
64-bit result = 0x4049aef3775b8130 

wo 0x4049aef3775b8130 tatsächlich 4632426052430037296 einmal umgewandelt wird wieder in Dezimalzahlen .

Wenn Sie wirklich eine Atom JS Nummer, Ihre letzte Option müssen, ist es zu konvertieren zurück in eine ganze Zahl mit 53-Bit-Genauigkeit:

var int53 = parseInt(hexHi + hexLo, 16); 
console.log(int53); 

Ausgang:

4632426052430037000