创建一个大位字段?

时间:2010-08-08 19:15:08

标签: javascript

我想在JavaScript中创建一个大位字段,它将有效地表示多维标记数组(使用索引来跳转到物理“1D”结构中的各个维度)。

而不是一堆数字,我正在考虑如何使用字符串作为位,所以我可以先分配一个适当长度的字符串。数据类型,Unicode和转换等注意事项发挥作用(在JavaScript 1.3之前也没有Unicode支持)。

但是,我对其他建议如何使用JavaScript来实现大位字段持开放态度。

更新
仅供参考:平均而言,我可能使用~2187位/标记(274字节),但想要一个通用的答案,而不是可以容纳更多的位。

4 个答案:

答案 0 :(得分:12)

字符串的一个问题是它们是不可变的,所以如果你想改变任何东西,你需要重建字符串。

我会坚持使用数字。使用按位运算符,每个数字可以匹配32位。

最多可以容纳53位,因为JavaScript数字是双精度浮点数,但是按位运算符将它们的操作数转换为32位整数,因此您将无法使用它们来获取单个位(如果你愿意的话,你可以通过除法组合Math.pow等来完成同样的事情,但它会更复杂。)

这是一个基本实现,可让您获取,设置和取消设置各个位:

function BitField() {
    this.values = []; // You could set the length here, but it's not necessary
}

BitField.prototype.get = function(i) {
    var index = (i / 32) | 0; // | 0 converts to an int. Math.floor works too.
    var bit = i % 32;
    return (this.values[index] & (1 << bit)) !== 0;
};

BitField.prototype.set = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    this.values[index] |= 1 << bit;
};

BitField.prototype.unset = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    this.values[index] &= ~(1 << bit);
};

答案 1 :(得分:4)

在最近的浏览器中,可以使用高效的数字数组类型。没有位数组,但您可以使用Uint8ArrayUint32Array并自己打包(以与Matthew Crumley的答案类似的方式;只使用数字数组而不是[]


Obselete但等效答案(CanvasPixelArray已替换为Uint8ClampedArray):

如果您定位的浏览器支持<canvas>,那么您可以借用CanvasPixelArray对象(canvas.getContext("2d").createImageData(...).data;请注意,这不一定与画布的大小相同)到(希望存储有效地存储数据(每个元素是一个八位字节)。如果您的数据是2D,您可以免费获得可视化效果!

答案 2 :(得分:3)

这是2010年Matthew Crumley's post的扩展名:

我使用了Matthew的代码,添加了预分配并将其与类型化数组实现进行了比较。

This jsperf表明Chrome是最快且最安全的(我希望Uint32Array执行速度最快)并且IE仅定义了接口但不关心优化类型化数组。 Firefox的结果很模糊,因为控制台上充斥着有关JSPerf如何“编译”测试代码的警告。

enter image description here

(“其他”是(我显然非常私密)IE 11。)

Uint8Array实施

function BitField8(nSize) {
    var nBytes = Math.ceil(nSize/8) | 0;
    this.values = new Uint8Array(nBytes);
}

BitField8.prototype.get = function(i) {
    var index = (i / 8) | 0;
    var bit = i % 8;
    return (this.values[index] & (1 << bit)) !== 0;
};

BitField8.prototype.set = function(i) {
    var index = (i / 8) | 0;
    var bit = i % 8;
    this.values[index] |= 1 << bit;
};

BitField8.prototype.unset = function(i) {
    var index = (i / 8) | 0;
    var bit = i % 8;
    this.values[index] &= ~(1 << bit);
};

Uint32Array实施

function BitField32(nSize) {
    var nNumbers = Math.ceil(nSize/32) | 0;
    this.values = new Uint32Array(nNumbers);
}

BitField32.prototype.get = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    return (this.values[index] & (1 << bit)) !== 0;
};

BitField32.prototype.set = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    this.values[index] |= 1 << bit;
};

BitField32.prototype.unset = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    this.values[index] &= ~(1 << bit);
};

答案 3 :(得分:-1)

在chrome中,我得到大约10,000位。

var bitfield = 0;
var flag1 = 2 << 1;
var flag2 = 2 << 2;
var flagmax = 2 << 10000;
bitfield |= flagmax
if (bitfield & flagmax) {
    doSomething();
}