至於你提到的JS沒有按轉換不支持64位整數,所以你將無法獲得相同的輸出。您可以得到最接近的兩個32位整數,它們表示相同的64位整數,根據您的Protobuf庫期望的輸入類型,這可能也可能不起作用。
我建議看看在接受的答案this question toFloat64()函數。
下面是一個略微簡化的版本:
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];
}
讓我們試試看:
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);
輸出:
32-bit high word = 0x4049aef3
32-bit low word = 0x775b8130
64-bit result = 0x4049aef3775b8130
其中0x4049aef3775b8130確實4632426052430037296一次轉換回十進制。
如果你真的需要一個原子JS號碼,最後的選擇是把它與53位精度轉換回整數
var int53 = parseInt(hexHi + hexLo, 16);
console.log(int53);
輸出:
4632426052430037000