在JavaScript中使用整数作为位域

Mar*_*ich 4 javascript bit-fields

作为项目的一部分,我有一串0到3之间的数字,例如: 2030000000000000000030000000000000000003333212111221121301

我想通过一个URL传递这个字符串,所以我想我可以尝试使用一个位域,因为每个数字最多只使用2位.我在我的类中编写了以下函数,将这样的字符串转换为用作数据位域的整数数组:

makeBuildBitfield: function(build) {
var b = build.split('');
var f = [3, 0]; // the "3" is there for future purposes
var i = 1;
var j = 0;

for (var t in b) {
    if (j < 14) {
        f[i] |= b[t];
        f[i] = f[i] << 2;
        ++j;
    } else {
        f[i] |= b[t];
        ++i;
        f[i] = 0;
        j = 0;
    }
}

return f.join('.');
},

getBuildFromBitfield: function(bitfield) {
b = bitfield.split('.');

var ba = [];
for (var x = 1; x < b.length; ++x) { //start from 1 to skip the "3"
    ba[x] = [];
    var n = b[x];
    for (var y = 14; y >= 0; --y) {
        ba[x][y] = n & 3;
        n = n >>> 2;
    }
}

build = '';
for (var a in ba) build += ba[a].join('');
return build;
},
Run Code Online (Sandbox Code Playgroud)

他们似乎确实在工作,但......并不完全.当我从开头的示例中传递字符串时:

2030000000000000000030000000000000000003333212111221121301
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

3.587202560.786432.4089.156916164
Run Code Online (Sandbox Code Playgroud)

但是,当我将它传递给应该将其转换回来的函数时,它给了我:

203000000000000000003000000000000000000333321021112211213010
Run Code Online (Sandbox Code Playgroud)

请注意第二个字符串中的额外零.现在,我是新手操作钻头,这是我第一次尝试它,但我已经四处搜索并阅读了我能找到的关于这个主题的文章,我试着在一张纸上写下来循环过程中的位状态以尝试理解发生了什么,但我似乎无法弄清楚它为什么会出错以及那些额外的零在那里做什么.我的string->bitfield功能是关闭的,或者是另一个,或者很可能两者兼而有之.但我真的无法弄清楚,所以有没有人有任何建议,我怎么能解决那些出错的问题?

提前致谢!

Dag*_*bit 7

这是一个很好的简短方法,可以将位域缩小到36个字符串.它也适用于基数为10的字符串,但这有点浓缩.它也适用于位域中的前导零.

function shrink (s) {
  for (var p=0, l=s.length, r=''; p<l; p+=25) { 
    r+=parseInt('1'+s.substring(p,p+25),4).toString(36); 
  }
  return r;
}

function expand (s) {
  for (var p=0, l=s.length, r=''; p<l; p+=10) { 
    r+=parseInt(s.substring(p,p+10), 36).toString(4).substring(1);
  }
  return r;
}
Run Code Online (Sandbox Code Playgroud)

编辑 - 我假设你的目标是缩小位域,通过url发送它(一个GET请求),然后在另一侧展开它.这将允许您这样做,虽然除了传输和扩展之外,您将无法对缩小的数据执行任何有用的操作.

编辑2 - 这是一个"无点"变体.这是一个测试:

var bits =  "0000000000000000000000000000000032222000" +
            "0000000000000000000000000000000031111300" +
            "0000000000000000000002111300000002111200" +
            "0000000000000000000003111120000003111130" +
            "0000000000000000000000021111200000111120" +
            "0000000000000320000000000211112000311110" +
            "0000000000002111123000000031111130011113" +
            "0000000000000321111111230000311112031111" +
            "0000000000000000032111111123002112200000" +
            "0000000032223300000000021111112000000000" +
            "0000000021111111112233000332130000000000" +
            "0330000000033322111111111111003330000000" +
            "2112000000000000000003222112001113000000" +
            "2112000111111111111112222220001113000000" +
            "2112000222222111111111111120001113000000" +
            "2112000000000000000033222230001113000000" +
            "2112003111111111111111111120001113000000" +
            "2112000000000000000000000000001113000000" +
            "2112333333333333333333333333331113000000" +
            "2111111111111111111111111111111113000000" ;

var shrunk = shrink(bits);
// b33j9ynrb4b34c70cb9cb33j9ynrclf2iv9lsx6ocpgnayh8n4b33j9ys...

var restored = expand(shrunk);

alert ( "Worked: " + (bits===restored) + ", orig size: " 
      + bits.length + ", shrunk size: " + shrunk.length);

// Worked: true, orig size: 800, shrunk size: 320
Run Code Online (Sandbox Code Playgroud)


Poi*_*nty 1

有几个问题:

  1. 迭代数组时不要使用“for (var x in y)”类型的循环。始终使用索引。

  2. 添加到位域字符串的最后一个内容并不总是代表原始的 15 位数字。“get”函数始终假设每个位域组件具有相同的位数。

  3. 您遗漏了var一些局部变量声明。

这是我的版本,至少适用于您的示例输入:

  makeBuildBitfield: function(build) {
    var b = build.split('');
    var f = [3, 0]; // the "3" is there for future purposes
    var i = 1, j = 0;;

    for (var t = 0; t < b.length; ++t, ++j) {
        if (j === 15) {
          f[++i] = 0;
          j = 0;
        }
        f[i] = (f[i] << 2) + (b[t] & 3);
    }

    f[0] = j === 0 ? 15 : j;
    return f.join('.');
  },

  getBuildFromBitfield: function(bitfield) {
    var b = bitfield.split('.');

    var ba = [];
    for (var x = 1; x < b.length; ++x) { //start from 1 to skip the "3"
        ba[x] = [];
        var n = b[x];
        for (var y = (x === b.length - 1 ? parseInt(b[0], 10) : 15); --y >= 0; ) {
            ba[x][y] = n & 3;
            n = n >>> 2;
        }
    }

    var build = '';
    for (var a = 1; a < ba.length; ++a) {
      build += ba[a].join('');
    }
    return build;
  }
Run Code Online (Sandbox Code Playgroud)

我偷了你的“f[0]”作为最后一个条目的大小,但你可以把这个值放在任何地方。