Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to convert from 4x Uint8 into Uint32 using typed arrays in JavaScript?

I'm doing some bitwise manipulation in a project and I wonder if the built-in typed arrays might save me some headache and maybe even give me a bit of a performance gain.

let bytes = [128, 129, 130, 131]
let uint32 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]
//=> -2138996093

Can I use typed arrays to get the same answer ?

// not actually working !
let uint8bytes = Uint8Array.from(bytes)
let uint32 = Uint32Array.from(uint8bytes)[0]
//=> ideally i'd get the same value as above: -2138996093

Side question:

I found it strange that the uint32 above is negative – obviously not very ... unsigned as the name of the var suggests ...

If I mash together binary octets and parse it, I get the complimentary positive answer

//         128          129          130          131
let bin = '10000000' + '10000001' + '10000010' + '10000011'
let uint32 = Number.parseInt(bin,2)

console.log(uint32)
// 2155971203 

It's no surprise that I can reverse the process to get the correct values out of each, but I don't understand why procedure 1 is negative but procedure 2 is positive.

let a = -2138996093;
let b = 2155971203;

// two's compliment, right?
console.log(a.toString(2)) // -1111111011111100111110101111101
console.log(b.toString(2)) // 10000000100000011000001010000011

console.log(a >> 24 & 255) // 128
console.log(a >> 16 & 255) // 129
console.log(a >> 8 & 255)  // 130
console.log(a >> 0 & 255)  // 131

console.log(b >> 24 & 255) // 128
console.log(b >> 16 & 255) // 129
console.log(b >> 8 & 255)  // 130
console.log(b >> 0 & 255)  // 131
like image 245
Mulan Avatar asked Sep 10 '16 04:09

Mulan


People also ask

What is typed array in JavaScript?

JavaScript typed arrays are array-like objects that provide a mechanism for reading and writing raw binary data in memory buffers. Array objects grow and shrink dynamically and can have any JavaScript value. JavaScript engines perform optimizations so that these arrays are fast.

Why might you use typed arrays instead of standard arrays?

A typed array significantly simplifies the level of proof the engine needs to be able to optimise around it. A value returned from a typed array is certainly of a certain type, and engines can optimise for the result being that type.

What is array of uint8?

The elements of a uint8 array can range from 0 to 255. Values outside this range are mapped to 0 or 255. If A is already an unsigned 8-bit integer array, uint8 has no effect. The fractional part of each value in A is discarded on conversion. This means, for example, that uint8(102.99) is 102, not 103.

How do you concatenate Uint8Array?

You can use the set method. Create a new typed array with all the sizes. Example: var arrayOne = new Uint8Array([2,4,8]); var arrayTwo = new Uint8Array([16,32,64]); var mergedArray = new Uint8Array(arrayOne.


1 Answers

The best way to handle this is with a DataView - that way you can specify the endianness of the value you want to get - your code is using bigendian values for the int32

let bytes = [128, 129, 130, 131];
let uint8bytes = Uint8Array.from(bytes);
let dataview = new DataView(uint8bytes.buffer);
let int32le = dataview.getInt32(0, true); // second parameter truethy == want little endian
let int32be = dataview.getInt32(0); // second parameter absent or falsey == want big endian
console.log(int32le); // -2088599168
console.log(int32be); // -2138996093

The reason

let uint32 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]

returns a SIGNED int is that the bitwise operators (<<, |) coerce the values to a signed 32 bit value

like image 78
Jaromanda X Avatar answered Oct 02 '22 19:10

Jaromanda X