如果二进制数据的大小大于32位,如何“旋转"(水平方向)二进制数据? [英] How to “rotate” the binary data (in horizontal direction) if its size is greater than 32 bits?

查看:155
本文介绍了如果二进制数据的大小大于32位,如何“旋转"(水平方向)二进制数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下TypedArray(请注意,此数据的大小为80位):

I have the following TypedArray (note that the size of this data is 80 bits):

var arr = new Uint8Array([10, 110, 206, 117, 200, 35, 99, 2, 98, 125]);

,我想将其旋转N位(其中N是从0到79的任何整数).例如,如果N = 50,我将这样表示:

and I want to rotate it by N bits (where N is any integer from 0 to 79). For example, if N=50, I will represent it like this:

00001010 01101110 11001110 01110101 11001000 00100011 01100011 00000010 01100010 01111101
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

所以结果应该是

01101100 01100000 01001100 01001111 10100001 01001101 11011001 11001110 10111001 00000100
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

所以arr[0]等于108,arr[1]等于96等等.如何解决这个问题?

so arr[0] will be equal to 108, arr[1] will be equal to 96 etc. How to solve this?

推荐答案

要按位移位整个字节数组,您可以执行以下操作:

To shift an entire byte-array bit-wise you can do:

  • 首先计算可以移动多少字节(var bytes = (bits / 8)|0;)
  • 从一端复制字节数,将字节移过来,将前一个切片粘贴到另一端
  • 检查是否还有剩余的位(var剩下的= bits % 8)
  • 如果还有剩余(!= 0),则循环遍历,将前一个字节复制并移位相反方向的位数和8个剩余的位数(var prev = arr[arr.length - 1] << (8- remainder);)(有关详细信息,请参见演示).
  • 将字节移位并与上一个移位字节(arr[i] = (arr[i]>>>remainder) | prev;)合并
  • First calculate how many bytes can be shifted (var bytes = (bits / 8)|0;)
  • Copy the number of bytes from one end, shift bytes over, paste previous slice in at the opposite end
  • Check if there is any bits remaining (var remainder = bits % 8)
  • If any remainder (!=0) left then loop through, copy and shift previous byte the number of bits in opposite direction and 8-remainding bits (var prev = arr[arr.length - 1] << (8- remainder);) (see demo for details).
  • Shift byte over and merge with previous shifted byte (arr[i] = (arr[i]>>>remainder) | prev;)

// main rotation function
function rotate(arr, bits) {

  var arrBits = arr.length<<3;
  var aBits = Math.abs(bits) % arrBits;       // "clamp" and make positive value
  aBits = bits < 0 ? arrBits - aBits : aBits; // direction

  var bytes = (aBits / 8)|0;       // how many bytes we can pre-rotate
  var remainder = aBits % 8;       // number of additional bits that needs to rotate
  var iRemainder = 8 - remainder;  // inverse (cached for convenience)
  var first;                       // first shift added to end

  // first rotate based on number of whole bytes, get slice of end
  var rBytes = arr.slice(arr.length - bytes);
   
  // shift over remainding array byte-wise
  arr.copyWithin(bytes, 0);
   
  // set previous slice from end to beginning
  arr.set(rBytes);
   
  // shift remainders, if any (>0)
  if (remainder) {
    first = (arr[arr.length - 1] << iRemainder);    // need this at the end
	
    for(var i = arr.length-1; i > 0; i--) {         // iterate in reverse
      var prev = (arr[i - 1] << iRemainder);        // get previous byte shifted
      arr[i] = (arr[i]>>>remainder) | prev;         // shift current, merge w/prev
    }
    arr[0] = (arr[0]>>>remainder) | first           // shift last and merge w/first
  }
}

// DEMO STUFF -
var rng = document.getElementById("bits");
var cnt = document.getElementById("cnt");
var out = document.getElementById("out");
function toBin(arr) {
  for(var i=0, str="", str2=""; i < arr.length; i++) {
    str+= pad(arr[i]) + " ";
    str2 += arr[i].toString() + " ";
  }
  return str.replace(/0/g, "<span class=c>0</span>") + "<br>" + str2;
}
function pad(b) {
  var s = "00000000" + b.toString(2);
  return s.substr(s.length - 8)
}
function update() {
  var arr = new Uint8Array([10, 110, 206, 117, 200, 35, 99, 2, 98, 125]);
  cnt.innerHTML = rng.value;  rotate(arr, +rng.value); out.innerHTML = toBin(arr)
}
update(); rng.oninput = update;

body {font:16px sans-serif;margin-left:0}
#out {font:12px monospace;white-space:nowrap}
.c {color:#999} div {margin-top:10px}

<label>Bits: <input id=bits type=range min=-80 max=80 value=0></label> <span id=cnt>0</span>
<div id=out></div>

要反方向旋转,只需从总位数(arrayByteLength x 8-位)中减去位数,只需记住对基于数组长度的结果取模即可.

To rotate the opposite direction simply subtract number of bits from total number of bits (arrayByteLength x 8 - bits), just remember to apply modulo on the result based on array length.

这篇关于如果二进制数据的大小大于32位,如何“旋转"(水平方向)二进制数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆