#javascript #logic #byte #integer-arithmetic
Вопрос:
В последнее время я занимаюсь некоторой работой по логической арифметике. Я хочу кодировать целые числа без знака (Uint) и целые числа со знаком (Int) в байтах.
Ниже приведен фрагмент кода, который в настоящее время преобразует UInts в байты и наоборот. К сожалению, у меня возникли некоторые проблемы при кодировании целых чисел со знаком с помощью моей тактики.
Кодирование целых чисел будет выполняться с использованием этого метода сдвига и маски как для целых чисел без знака, так и для целых чисел со знаком.
for (let i=0; ilt;n; i ) buffer.push((value gt;gt;gt; (i*8)) amp; 0xFF);
Так что же не так с моим readInt
методом и как это исправить?
const buffer = []; const writeIntN = (value, n) =gt; { for (let i=0; ilt;n; i ) buffer.push((value gt;gt;gt; (i*8)) amp; 0xFF); } const readUint = (n, offset) =gt; { let v=0; for (let i=0; ilt;n; i ) v |= (buffer[offset ] lt;lt; (i*8)); return v gt;gt;gt; 0; } const readInt = (n, offset) =gt; { return readUint(n, offset) lt;lt; (8*n) gt;gt; (8*n); // error is here } const writeUInt16 = (value) =gt; writeIntN(value, 2); const readUInt16 = (offset) =gt; readUint(2, offset); const writeInt16 = (value) =gt; writeIntN(value, 2); const readInt16 = (offset) =gt; readInt(2, offset); const writeInt8 = (value) =gt; writeIntN(value, 1); const readInt8 = (offset) =gt; readInt(1, offset); writeUInt16(20); writeInt16(-20); writeInt8(-42); console.log(buffer); console.log(readUInt16(0)); console.log(readInt16(2)); console.log(readInt8(4)); // how?
Примечание: Я знаю об основных операциях декодирования 8,16-битных подписанных входов, но как сделать это более эффективным внутри цикла for readUint
?
Декодирование 8-разрядных целых чисел со знаком: (buffer[offset ] lt;lt; 24) gt;gt; 24
Декодирование 16-разрядных целых чисел со знаком: (((buffer[offset ] lt;lt; 0) | (buffer[offset ] lt;lt; 8)) lt;lt; 16) gt;gt; 16
Ответ №1:
Так что же не так с моим методом чтения и как это исправить?
Исправление: измените (8*n)
на (8*(4-n))
.
const readInt = (n, offset) =gt; { return readUint(n, offset) lt;lt; (8*(4-n)) gt;gt; (8*(4-n)); }
Или, что эквивалентно,
const readInt = (n, offset) =gt; { let v =0; for (let i=4-n; ilt;4; i ) v |= (buffer[offset ] lt;lt; (i*8)); return v gt;gt; (8*(4-n)); }
Побитовые операторы JavaScript используют 32-разрядные (4-байтовые) целые числа. Оператор left shift ( lt;lt;
) отбрасывает биты, сдвинутые влево. Оператор сдвига вправо ( gt;gt;
) распространяет крайний левый (знаковый) бит.
console.log(); writeUInt16(20); writeInt16(-20); writeInt8(-42); console.log(buffer); console.log(readUInt16(0)); console.log(readInt16(2)); console.log(readInt8(4)); [ 20, 0, 236, 255, 214 ] 20 -20 -42
const buffer = []; const writeIntN = (value, n) =gt; { for (let i=0; ilt;n; i ) buffer.push((value gt;gt;gt; (i*8)) amp; 0xFF); } const readUint = (n, offset) =gt; { let v=0; for (let i=0; ilt;n; i ) v |= (buffer[offset ] lt;lt; (i*8)); return v gt;gt;gt; 0; } const readInt = (n, offset) =gt; { return readUint(n, offset) lt;lt; (8*(4-n)) gt;gt; (8*(4-n)); } const writeUInt32 = (value) =gt; writeIntN(value, 4); const readUInt32 = (offset) =gt; readUint(4, offset); const writeInt32 = (value) =gt; writeIntN(value, 4); const readInt32 = (offset) =gt; readInt(4, offset); const writeUInt16 = (value) =gt; writeIntN(value, 2); const readUInt16 = (offset) =gt; readUint(2, offset); const writeInt16 = (value) =gt; writeIntN(value, 2); const readInt16 = (offset) =gt; readInt(2, offset); const writeUInt8 = (value) =gt; writeIntN(value, 1); const readUInt8 = (offset) =gt; readUint(1, offset); const writeInt8 = (value) =gt; writeIntN(value, 1); const readInt8 = (offset) =gt; readInt(1, offset); writeUInt32(Math.pow(2,32)-1); writeInt32((1lt;lt;31)-1); writeInt32(-(1lt;lt;31)); writeUInt16((1lt;lt;16)-1); writeInt16((1lt;lt;15)-1); writeInt16(-(1lt;lt;15)); writeUInt8((1lt;lt;8)-1); writeInt8((1lt;lt;7)-1); writeInt8(-(1lt;lt;7)); console.log(buffer); console.log(readUInt32(0)); console.log(readInt32(4)); console.log(readInt32(8)); console.log(readUInt16(12)); console.log(readInt16(14)); console.log(readInt16(16)); console.log(readUInt8(18)); console.log(readInt8(19)); console.log(readInt8(20));
[ 255, 255, 255, 255, 255, 255, 255, 127, 0, 0, 0, 128, 255, 255, 255, 127, 0, 128, 255, 127, 128 ] 4294967295 2147483647 -2147483648 65535 32767 -32768 255 127 -128