如何在JavaScript中从ArrayBuffer/DataView读取64位整数 [英] How to Read 64-bit Integer from an ArrayBuffer / DataView in JavaScript
本文介绍了如何在JavaScript中从ArrayBuffer/DataView读取64位整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
给出一个64位(8字节)的字节序的
Given a 64-bit (8-byte) little-endian ArrayBuffer
of bytes, how can we read 64-bit integer values in JavaScript?
我进行了实验并提出了这个建议,但是鉴于 DataView
尚未提供 getUint64()
,还有更好的解决方案吗?
I experimented and came up with this, but is there a more elegant solution given that DataView
does not yet provide getUint64()
?
const bytes = new Uint8Array([ 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff ]);
// [----- left -----] [---- right ----]
const view = new DataView(bytes.buffer);
// split 64-bit number into two 32-bit numbers
const left = view.getUint32(0, true); // 4294967295
const right = view.getUint32(4, true); // 4294967295
// combine the 2 32-bit numbers using max 32-bit val 0xffffffff
const combined = left + 2**32*right;
console.log('combined', combined);
// 18,446,744,073,709,552,000 is returned Javascript for "combined"
// 18,446,744,073,709,551,615 is max uint64 value
// some precision is lost since JS doesn't support 64-bit ints, but it's close enough
推荐答案
基于原始实验和 Sebastian Speitel
的建议/修正,此函数将返回64位值,直到
Based on the original experiment and Sebastian Speitel
's suggestion/fix, this function returns a 64-bit value until precision is lost after Number.MAX_SAFE_INTEGER
DataView.prototype.getUint64 = function(byteOffset, littleEndian) {
// split 64-bit number into two 32-bit parts
const left = this.getUint32(byteOffset, littleEndian);
const right = this.getUint32(byteOffset+4, littleEndian);
// combine the two 32-bit values
const combined = littleEndian? left + 2**32*right : 2**32*left + right;
if (!Number.isSafeInteger(combined))
console.warn(combined, 'exceeds MAX_SAFE_INTEGER. Precision may be lost');
return combined;
}
经过以下测试:
Tested below:
// [byteArray, littleEndian, expectedValue]
const testValues = [
// big-endian
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]), false, 255],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff]), false, 65535],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]), false, 4294967295],
[new Uint8Array([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]), false, 4294967296],
[new Uint8Array([0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), false, 9007199254740991], // maximum precision
[new Uint8Array([0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), false, 9007199254740992], // precision lost
[new Uint8Array([0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]), false, 9007199254740992], // precision lost
// little-endian
[new Uint8Array([0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), true, 255],
[new Uint8Array([0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), true, 65535],
[new Uint8Array([0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00]), true, 4294967295],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]), true, 4294967296],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00]), true, 1099511627776],
[new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]), true, 281474976710656],
[new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00]), true, 9007199254740991], // maximum precision
];
testValues.forEach(testGetUint64);
function testGetUint64([bytes, littleEndian, expectedValue]) {
const val = new DataView(bytes.buffer).getUint64(0, littleEndian);
console.log(val === expectedValue? 'pass' : 'FAIL. expected '+expectedValue+', received '+val);
}
这篇关于如何在JavaScript中从ArrayBuffer/DataView读取64位整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文