【问题标题】:How to mask ints using bitwise operators如何使用按位运算符屏蔽整数
【发布时间】:2012-05-03 23:45:39
【问题描述】:

我想知道是否有一种方法可以使用按位运算符屏蔽 int 值列表,并使用该掩码来了解 int 值是否是掩码中的值之一。

即如果我有值 129 和 17,如何计算一个掩码,告诉我掩码中是否有一个 int 值对应(如果 int 值是 129 或 17)。

我希望下一个伪代码能更好地理解我的问题。

**编辑: 我想仅在一个值(掩码)中打包、屏蔽或“压缩”一个 int 数组,然后只接受要屏蔽的值列表中的值(数组)。

有可能吗?提前致谢。

valuesToMask = [17, 129, ...]
mask = getmask(valuesToMask)
lstValues = [0,1, 10, ..., 17, 18, 19, ..., 129, ...]
foreach(int value, in lstValues) {
    if(check(mask,value)) 
       printf("\nValue %d is in the mask", value);
    else 
       printf("\nValue %d is not in the mask", value);
}

提前致谢。非常感谢您的帮助和您的时间。

(对不起我的英语)

【问题讨论】:

    标签: bit-manipulation bitwise-operators bitmask bloom-filter


    【解决方案1】:

    您可以对 某些 组值执行此操作,但通常不一定如此。例如,如果你想确定一个值是 4、5、6 还是 7,那么你可以这样做:

    if ((value & ~3) == 4) ...
    

    这将创建一个掩码,除最低有效两位外,所有位都为 1。 & 运算符有效地将最低有效两位设置为 0。然后比较检查位模式是否与您要查找的值匹配。在二进制表示中,如下所示(假设 value 是一个 8 位值):

    value        masked
    00000011     00000000 = 0
    00000100     00000100 = 4
    00000101     00000100 = 4
    00000110     00000100 = 4
    00000111     00000100 = 4
    00001000     00001000 = 8
    

    如果您只想检查“4、5 或 7”,则此技术将不起作用。

    【讨论】:

    • 所以必须继续使用这种技术检查的值?
    • 不,这只是我使用的示例。例如,您可以使用 (value & ~6) == 8 检查 8 到 14 之间的偶数。
    【解决方案2】:

    您可以使用Bloom Filters部分解决您的问题。其工作方式是,为了测试 N-set 项目的成员资格,您定义 K 散列函数以将每个项目映射到 M-bit 密钥。对于插入元素a,将位置h1(a) ... hk(a) 的过滤器的位设置为等于1。对于查找元素b,如果在h1(b) 的任何位置检测到零位...hk(b),然后b 保证不在集合中。然而,根据 N、M 和 K 的值,您得到误报的可能性很小(即,您没有从哈希函数中检测到零,但 b 之前没有存储在过滤器中)。

    在伪代码中:

    const int M = 256;
    typedef std::bitset<M> Mask;
    
    int listValues[N] = { v1, ... , vN };
    typedef unsigned char (*)(int) HashFunction; // maps int to 0...255
    HashFunction hash[K] = { h1, ..., hK };
    
    Mask make_mask(int x)
    {
        Mask m(0):
        for (int i = 0; i < K; ++i) { 
            m[(hash[i])(x)] = 1; // update mask with item's hash
        }
        return(m);
    }    
    
    // initialize
    Mask BloomFilter(0);
    for (int i = 0; i < N; ++i) {        
        BloomFilter |= make_mask(listValues[i]);
    }
    
    // probe
    bool is_not_in_filter(const Mask& F, int x)
    {
        // if a zero-bit in F matches a 1-bit in make_mask(x), then x is not in F
        return ~F & make_mask(x) != 0; 
    }
    
    // call
    int x = ...;
    bool in_set = is_not_in_filter(BloomFilter, x);
    

    实际上,这会将每个项目扩展为一个 M 位密钥,并且过滤器是所有项目的聚合按位或。然后,对集合成员的测试变成了一个简单的(尽管是概率的)在 NEGATED 过滤器与要测试的 M 位扩展项之间的按位与。

    更新: 上面的代码是伪代码来解释它是如何工作的。要获得一个实际的库,请参见例如实验性的Boost.Bloomfiltersbloom

    【讨论】:

    • 哇,我不知道,非常感谢您的帮助,我会检查它是如何工作的。谢谢
    • @Herman 查看实际库链接的更新答案。
    【解决方案3】:

    我想你问的是如何检查一个数字是 129 还是 17。

    int[] lstValues = [0,1, 10, 17, 18, 19, 129];
    foreach(int value in lstValues) {
        if(lstValues == 129 || lstValues == 17) 
            printf("\nValue is in the mask");
        else 
            printf("\nValue is not in the mask");
    }
    

    【讨论】:

    • 是的,就是这样,但是,我需要保留 129 和 17 作为唯一值
    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 2012-09-19
    • 1970-01-01
    • 2017-07-02
    相关资源
    最近更新 更多