給定一個(gè)64位(8字節(jié))的little-endian ArrayBuffer字節(jié),我們?nèi)绾卧?a >JavaScript中讀取64位整數(shù)值?
我進(jìn)行了實(shí)驗(yàn)并想出了這個(gè),但是有一個(gè)更優(yōu)雅的解決方案,因?yàn)镈ataView還沒(méi)有提供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"http:// 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
解決方法:
基于原始實(shí)驗(yàn)和Sebastian Speitel
的建議/修復(fù),此函數(shù)返回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;}
測(cè)試如下:
// [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);}
來(lái)源:https://www.icode9.com/content-1-493551.html
聯(lián)系客服