位掩码的大小是否有实际限制?

时间:2008-10-07 02:44:48

标签: sql bit-manipulation bitmask

通过使用位掩码,可以在一个变量中存储多个值。例如,如果用户对某个项目具有读取,写入和执行权限,则可以通过说出read = 4 (2^2), write = 2 (2^1), execute = 1 (2^0)将其转换为单个数字,然后将它们一起添加到7中。

我在几个Web应用程序中使用这种技术,我通常将变量存储到一个字段中,并为其提供一种MEDIUMINT或其他类型,具体取决于不同值的数量。

我感兴趣的是,您可以存储的值的数量是否存在实际限制?例如,如果数字超过64,则不能再使用(64位)整数。如果是这种情况,你会用什么?它会如何影响您的程序逻辑(即:您是否仍然可以使用按位比较)?

我知道,一旦你开始获得非常大的值集,一个不同的方法将是最佳解决方案,但我对这个方法的界限感兴趣。

7 个答案:

答案 0 :(得分:3)

在我的脑海中,我会写一个set_bitget_bit函数,它可以在数组中获取一个字节数组和一个位偏移量,并使用一些bit-twiddling来设置/获取数组中的相应位。这样的事情(在C中,但希望你能得到这个想法):

// sets the n-th bit in |bytes|. num_bytes is the number of bytes in the array
// result is 0 on success, non-zero on failure (offset out-of-bounds)
int set_bit(char* bytes, unsigned long num_bytes, unsigned long offset)
{
  // make sure offset is valid
  if(offset < 0 || offset > (num_bytes<<3)-1) { return -1; }

  //set the right bit
  bytes[offset >> 3] |= (1 << (offset & 0x7));

  return 0; //success 
}

//gets the n-th bit in |bytes|. num_bytes is the number of bytes in the array
// returns (-1) on error, 0 if bit is "off", positive number if "on"
int get_bit(char* bytes, unsigned long num_bytes, unsigned long offset)
{
  // make sure offset is valid
  if(offset < 0 || offset > (num_bytes<<3)-1) { return -1; }

  //get the right bit
  return (bytes[offset >> 3] & (1 << (offset & 0x7));
}

答案 1 :(得分:2)

我在文件系统代码中使用了位掩码,其中位掩码比机器字大许多倍。把它想象成“一连串的布尔”;

(如果你想知道,请在闪存中记录掩码)

许多编译器知道如何为您执行 。添加一些OO代码,使其具有可操作的类型,然后您的代码开始看起来像它的意图,而不是一些比特敲击。

我的2美分。

答案 2 :(得分:1)

使用64位整数,您可以存储最多2 ^ 64-1的值,64只是2 ^ 6。所以,是的,有一个限制,但如果你需要超过64个标志,我会非常有兴趣知道他们在做什么:)

您需要考虑多少个州?如果您有64个潜在状态,则它们可以存在的组合数是64位整数的完整大小。

如果你需要担心128个标志,那么一对位向量就足够了(2 ^ 64 * 2)。

加法:在编程Pearls中,对使用长度为10 ^ 7的位数组进行了扩展讨论,以整数实现(用于保存使用过的800个数字) - 它非常快,而且非常合适对于该章中描述的任务。

答案 3 :(得分:1)

有些语言(我相信perl确实不确定)允许对字符串进行逐位算术运算。为您提供更大的有效范围。 ((strlen * 8bit chars)组合)

但是,我不会使用单个值来叠加多个/类型/数据。 3位整数的基本r / w / x三元组可能是“实际”上限,不是出于空间效率的原因,而是出于实际发展的原因。

(Php使用这个系统来控制它的错误消息,我已经发现当你必须定义php的常量不是常驻的值并且你必须手动生成整数时它有点过顶了,说实话,如果chmod不支持'ugo + rwx'风格的语法,我永远不想用它,因为我永远不会记住神奇的数字)

你必须打开一个常量表来调试代码,你知道你已经走得太远了。

答案 4 :(得分:1)

旧线程,但值得一提的是,有些情况需要膨胀位掩码,例如分子指纹,它们通常生成为1024位数组,我们已经打包在32个bigint字段中(SQL Server不支持UInt32的)。一点一点的操作工作正常 - 直到你的表开始增长,你意识到单独的函数调用的迟缓。二进制数据类型是否有效,如果不是T-SQL禁止具有两个二进制操作数的按位运算符。

答案 5 :(得分:0)

例如,.NET使用整数数组作为其BitArray类的内部存储。 实际上没有别的办法了。

话虽如此,在SQL中,您需要多个列(或使用BLOBS)来存储所有状态。

答案 6 :(得分:0)

您已将此问题标记为SQL,因此我认为您需要查阅数据库的文档以查找整数的大小。然后为符号减去一位,只是为了安全。

编辑:您的评论说您正在使用MySQL。 MySQL 5.0 Numeric Types的文档指出NUMERIC的最大大小为64或65位。那是64位的212位数。

请记住,您选择的语言必须能够使用这些数字,因此您可能无论如何都可以限制为64位整数。