Converting javascript Integer to byte array and back
function intFromBytes( x ){
var val = 0;
for (var i = 0; i < x.length; ++i) {
val += x[i];
if (i < x.length-1) {
val = val << 8;
}
}
return val;
}
function getInt64Bytes( x ){
var bytes = [];
var i = 8;
do {
bytes[--i] = x & (255);
x = x>>8;
} while ( i )
return bytes;
}
I am trying to convert a javascript number to a byte array and then back to a number. However the above functions produce incorrect output with a very large number.
var array = getInt64Bytes(23423423);
var value = intFromBytes(array);
console.log(value); //Prints 23423423 - correct
var array = getInt64Bytes(45035996273704);
var value = intFromBytes(array);
console.log(value); //Prints -1030792152 - incorrect
It is my understanding that javascript floats are 53
bits so it shouldn't be overflowing? alert(Math.pow(2,53))
works fine.
Using the hint provided by Susanoh13, here are the two functions that allow conversion of number from/to ByteArray:
longToByteArray = function(/*long*/long) {
// we want to represent the input as a 8-bytes array
var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];
for ( var index = 0; index < byteArray.length; index ++ ) {
var byte = long & 0xff;
byteArray [ index ] = byte;
long = (long - byte) / 256 ;
}
return byteArray;
};
byteArrayToLong = function(/*byte[]*/byteArray) {
var value = 0;
for ( var i = byteArray.length - 1; i >= 0; i--) {
value = (value * 256) + byteArray[i];
}
return value;
};
In JavaScript bit shifts (>>
, <<
) are always performed on signed, 32-bits integers. This leads to range overflow for large numbers.
try (**
is power operator, <<
and >>>
are bit-shift operators) - intFromBytes
works only for arrays generated from positive integers
function getInt64Bytes(x) {
let y= Math.floor(x/2**32);
return [y,(y<<8),(y<<16),(y<<24), x,(x<<8),(x<<16),(x<<24)].map(z=> z>>>24)
}
function intFromBytes(byteArr) {
return byteArr.reduce((a,c,i)=> a+c*2**(56-i*8),0)
}
function getInt64Bytes(x) {
let y= Math.floor(x/2**32);
return [y,(y<<8),(y<<16),(y<<24), x,(x<<8),(x<<16),(x<<24)].map(z=> z>>>24)
}
function intFromBytes(byteArr) {
return byteArr.reduce((a,c,i)=> a+c*2**(56-i*8),0)
}
// TEST
let n = 40*2**40 + 245*2**32 + 194*2**24 + 143*2**16 + 92*2**8 + 40;
let b = getInt64Bytes(n);
let i = intFromBytes(b);
console.log(`number : ${n}`);
console.log(`int to bytes: [${b}]`);
console.log(`bytes to int: ${i}`);