给定一个64位(8字节)的little-endian ArrayBuffer字节,我们如何在JavaScript中读取64位整数值?
我进行了实验并想出了这个,但是有一个更优雅的解决方案,因为DataView还没有提供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 numbersconst left = view.getUint32(0, true); // 4294967295const right = view.getUint32(4, true); // 4294967295// combine the 2 32-bit numbers using max 32-bit val 0xffffffffconst 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位值,直到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;}
测试如下:
// [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);}
来源:https://www.icode9.com/content-1-493551.html
联系客服