Кодируйте Int в байты с помощью логических операторов

#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