代码之家  ›  专栏  ›  技术社区  ›  John K

创建一个大的位字段?

  •  8
  • John K  · 技术社区  · 14 年前

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

    我在考虑如何使用一个字符串作为位,这样我就可以先分配一个适当长度的字符串,而不是一堆数字。考虑到数据类型、Unicode和转换(在Javascript 1.3之前也不支持Unicode)。

    不过,我对如何使用javascript实现大字段的其他建议持开放态度。

    更新:
    仅供参考:平均而言,我可能会使用约2187位/标记(274字节),但我希望得到一个通用答案,而不是能够容纳更多位。

    4 回复  |  直到 10 年前
        1
  •  12
  •   Matthew Crumley    14 年前

    字符串的一个问题是它们是不可变的,所以如果您想更改任何内容,就需要重新生成字符串。

    我会坚持使用数字。使用位运算符,您可以在每个数字中容纳32位。

    因为javascript数字是双精度浮点,所以最多可以容纳53位,但是位运算符将其操作数转换为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);
    };
    
        2
  •  4
  •   Kevin Reid    11 年前

    在最近的浏览器中,有效的数字数组类型是可用的。没有位数组,但可以使用 Uint8Array Uint32Array 自己打包这些位(类似于Matthew Crumley的答案;只需使用数字数组而不是 [] )


    观察但等价的答案( CanvasPixelArray 已被替换为 Uint8ClampedArray ):

    如果目标浏览器支持 <canvas> ,那么你可以借一个 Canvaspixelaray公司 对象(对象) canvas.getContext("2d").createImageData(...).data ;请注意,这不需要和画布的大小相同,以便(希望)有效地存储数据(每个元素都是一个八位字节)。如果你的数据是二维的,你可以免费获得可视化效果!

        3
  •  3
  •   Community Dai    7 年前

    这是对Matthew Crumley's Post From 2010的扩展:

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

    This jsferf shows that chrome is the fastest and sanest(I would expect uint32array to perform the fastest)and that ie only defined the interfaces but did care to optimize typed array.由于控制台中充斥着有关JSPERF如何“编译”测试代码的警告,因此火狐的结果会变得模糊。

    (“另一个”是(我显然非常私密)即11。)

    uint8array implementation

    函数bitfield8(nsize){
    var nbytes=math.ceil(nsize/8)0;
    this.values=新的uint8array(nbytes);
    }
    
    bitfield8.prototype.get=函数(i){
    VaR指数=(i/8)0;
    var位=i%8;
    返回(this.values[index]&(1<<bit))!=0;
    };
    
    bitfield8.prototype.set=函数(i){
    VaR指数=(i/8)0;
    var位=i%8;
    this.values[index]=1<<位;
    };
    
    bitfield8.prototype.unset=函数(i){
    VaR指数=(i/8)0;
    var位=i%8;
    this.values[index]&=~(1位);
    };
    < /代码> 
    
    

    uint32arrayimplementation

    函数bitfield32(nsize){
    var nnumbers=math.ceil(nsize/32)0;
    this.values=新的uint32数组(nnumbers);
    }
    
    bitfield32.prototype.get=函数(i){
    VaR指数=(i/32)0;
    var位=i%32;
    返回(this.values[index]&(1<<bit))!=0;
    };
    
    bitfield32.prototype.set=函数(i){
    VaR指数=(i/32)0;
    var位=i%32;
    this.values[index]=1<<位;
    };
    
    bitfield32.prototype.unset=函数(i){
    VaR指数=(i/32)0;
    var位=i%32;
    this.values[index]&=~(1位);
    };
    < /代码> 
    2010:

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

    This jsperf显示Chrome是最快和最健康的(我希望Uint32Array为了执行得最快),IE只定义了接口,但不关心优化类型化数组。由于控制台上充斥着关于JSPERF如何“编译”测试代码的警告,因此火狐的结果会变得模糊。

    enter image description here

    (“另一个”是(我显然非常私密)即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);
    };
    

    UIT32阵列实施

    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);
    };
    
        4
  •  -1
  •   Matt Williamson    14 年前

    在铬合金中,我得到大约10000比特。

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