4

Я делаю побитовое манипулирование в проекте, и мне интересно, могут ли встроенные типизированные массивы сэкономить мне некоторую головную боль и, возможно, даже дать мне немного прироста производительности.Можно ли конвертировать из 4x Uint8 в Uint32 с помощью типизированных массивов в JavaScript?

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

Могу ли я использовать типизированные массивы, чтобы получить тот же ответ?

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

Боковой вопрос:

Я нашел, что это странно, что выше uint32 отрицательный - явно не очень ... беззнаковое как имя вар предлагает ...

Если я месил двоичные октеты и разбираю его, я получаю бесплатный положительный ответ

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

 
console.log(uint32) 
 
// 2155971203

Это не удивительно, что я могу изменить процесс, чтобы получить правильные значения из каждого, но я не понимаю, почему процедура 1 является отрицательным, но процедура 2 положительна.

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

+0

вы не можете получить отрицательное число из UNSIGNED int32! –

+0

@JaromandaX I * сделал * комментарий на том, что в середине моего вопроса ...: \ – naomik

+0

Почему бы вам не попробовать Int32Array? –

ответ

2

Лучший способ справиться с этим с DataView - таким образом, вы можете указать endienness значения вы хотите получить - ваш код использует bigendien значения для 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 endien 
let int32be = dataview.getInt32(0); // second parameter absent or falsey == want big endien 
console.log(int32le); // -2088599168 
console.log(int32be); // -2138996093 

причина

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

возвращает SIGNED int, что побитовые операторы (<<, |) принуждают значения к значению 32-битного значения

+0

Это именно то, что я искал^_ ^ – naomik