简体   繁体   中英

JavaScript: Read 8 bytes to 64 bit integer

I have a buffer object which contains eight bytes. These eight bytes should now be interpreted as 64 bit integer.

Currently I use following algorithm:

var int = buff[0];

for (var i = 1; i < buff.length; i++) {
    int += (buff[i] * Math.pow(2, 8 * i));
}

console.log(int);

this works but I believe there are better ways (maybe using Uint64Array).

Unfortunately I cannot find how a Uint16Array could help me here for.

Regards

Update:

// puts two 32bit integers to one 64bit integer
var bufInt = (buf.readUInt32BE(0) << 8) + buf.readUInt32BE(4);

Javascript does not support 64 bit integers, because the native number type is a 64-bit double, giving only 53 bits of integer range.

You can create arrays of 32-bit numbers (ie Uint32Array ) but if there were a 64-bit version of those there'd be no way to copy values from it into standalone variables.

You can use node-int64 for 64-bit integer support:

var Int64 = require('node-int64');
var int64 = new Int64(buff);

从最新的 Node.js v12.0.0 开始,您现在可以使用buf.readBigUInt64LE :))

For a pity, correct answer is that Javascript not supports 64 bit integers (till now).

So, trying to get exact 64bit integer stored into your 8 bytes into single JS number-type variable will fail. Anyway.

Some decisions:

  1. Exact bits from 0 to 52:

If you do not need upper 11 bits of 64bit and it's enought for you to deal with exact 53-bit integers, you can use this way:

// puts up to 53 bits by 32bit integers to one "64bit" integer
var bufInt = (buf.readUInt32BE(0) & 0x001FFFFF) * 4294967296 + buf.readUInt32BE(4);

(edited question)

  1. "64bit" int with possible loose of low 11 bit correct states:

Otherwise, if you need "common big value" of 64bit and you don't interest about exact values of till 11 low bits (rightmost 2-3 digits of huge 64bit value), you can use this way:

// puts 64 bit value by 32bit integers to one "64bit" integer
// with possible loose of lower 11 bits correctness
var bufInt = buf.readUInt32BE(0) * 4294967296 + buf.readUInt32BE(4);

For those who interest int64 (64 bit integers support) in Javascript, BEWARE!

Look:

var x1 = 1 << 30;
var x2 = 1 << 31;
var x3 = 1 << 32;
var x4 = 1 << 33;
var a = 1240611072103715194;
var b = 1240611072103715193;
var c = 1240611072103700000;
alert(''
    + 'x1=' + x1 + ' (should =1073741824)\n' 
    + 'x2=' + x2 + ' (should =2147483648)\n' 
    + 'x3=' + x3 + ' (should =4294967296)\n' 
    + 'x4=' + x4 + ' (should =8589934592)\n' 
    + 'a=' + a + ' (should =1240611072103715194)\n' 
    + 'a-b=' + (a-b) + ' (should =1)\n'
    + 'a-c=' + (a-c) + ' (should =15194)\n'
);

RESULT:

x1=1073741824 (should =1073741824)
x2=-2147483648 (should =2147483648)
x3=1 (should =4294967296)
x4=2 (should =8589934592)
a=1240611072103715000 (should =1240611072103715194)
a-b=0 (should =1)
a-c=15104 (should =15194)

As javascript dont support 64bit integer readily,here is one solution that worked for me.Here i am converting 8 Byte unix timestamp.

inputString = "0000016b40d8ea30"    
var buf = Buffer.from(inputString, 'hex');
timestamp = (parseInt(buf.toString("hex"),16).toString());
console.log(timestamp); //1560161086000

There are some modules around to provide 64bit integer support:

Maybe your problem can be solved using one of those libraries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM