验证一个二进制数组是否是C中另一个数组的子集

验证一个二进制数组是否是C中另一个数组的子集,c,bit-manipulation,subset,C,Bit Manipulation,Subset,我需要验证字节数组(即字符)中的位是否是相同类型的另一个数组的子集:例如,0001.0011(19)是0011.0011(51)的子集,而0000.1011(11)不是 我开始玩逐位运算,几乎用XOR/OR/XOR序列解决了它: int is_subset (char *set_a, char *set_b, int size) { /* The operation is performed with three bitwise operations, resulting in a *

我需要验证字节数组(即字符)中的位是否是相同类型的另一个数组的子集:例如,0001.0011(19)是0011.0011(51)的子集,而0000.1011(11)不是

我开始玩逐位运算,几乎用XOR/OR/XOR序列解决了它:

int is_subset (char *set_a, char *set_b, int size)
{
  /* The operation is performed with three bitwise operations, resulting in a
   * sequence of bits that will be equal to zero if set_a is a subset of
   * set_b. As a bonus, the positions where the sets differ will be
   * available in the resulting sequence, and thus the number of differing
   * positions can be obtained by counting the number of bits set (for exemple,
   * with __builtin_popcount in GCC).
   *
   *   Exemple (TRUE):              Exemple (FALSE):
   *   ================             ================
   *   set_a   00010011             set_a   00001011
   *   set_b   00110011             set_b   00110011
   *   ----------------             ----------------
   *   XOR     00100000             XOR     00111000
   *   set_b   00110011             set_b   00110011
   *   ----------------             ----------------
   *   OR      00110011             OR      00111011
   *   set_b   00110011             set_b   00110011
   *   ----------------             ----------------
   *   XOR     00000000             XOR     00001000
   */

  int i;
  for (i = 0; i < size; i++)
    if ( (((set_a[i] ^ set_b[i]) | set_b[i]) ^ set_b[i]) != 0)
      return FALSE;

  return TRUE;
}
int是子集(char*set\u a,char*set\u b,int size)
{
/*该操作通过三个位操作执行,结果是
*如果集合_a是其子集,则等于零的位序列
*集合b。作为奖励,集合不同的位置将
*在结果序列中可用,因此不同的
*可以通过计算设置的位数来获得位置(例如,
*使用GCC中的内置popcount)。
*
*示例(真):示例(假):
*   ================             ================
*组a 00010011组a 00001011
*成套设备00110011成套设备00110011
*   ----------------             ----------------
*XOR 00100000 XOR 00111000
*成套设备00110011成套设备00110011
*   ----------------             ----------------
*或00110011或00111011
*成套设备00110011成套设备00110011
*   ----------------             ----------------
*XOR 00000000 XOR 000011000
*/
int i;
对于(i=0;i
但如果
set_a
为零(0000.0000),则它将失败(始终返回TRUE)。我尝试了不同的策略(比如bloomfilters),但可能是因为我的编程技巧,它远远不够快,或者至少不够优雅

有没有任何标准、优雅的方法可以毫无例外地做到这一点


编辑:明确地说,在此上下文中,“子集”意味着第一个数组(set_a)中的所有位TRUE在第二个数组(set_b)中也是TRUE。第二个数组中可能有其他位为真,但在第一个数组中是否为假并不重要。

a
b的子集
a
中的每一位都意味着
b

a -> b
或同等地

~a | b //not a or b
应给出
1111111

但是,对零进行否定测试可能更简单(检查是否没有在a中设置了位,但在b中没有设置位的情况)


int是子集(char*set\u a,char*set\u b,int size)
{
int i;
对于(i=0;i

我不记得按位填充是否能正确处理字符,或者是否需要先转换为unsigned。

a
b
的子集,当且仅当
(a | b)==b
。如果每个字节都满足此条件,则返回
TRUE
。否则返回
FALSE


或者相当于
(a&b)==a

如果集合a是一个零数组,我不确定说你的代码失败仅仅因为它返回TRUE是正确的,因为从纯理论的数学观点来看,空集是任何其他集合的子集。如果您不喜欢,那么您应该添加一个额外的检查,看看set_a是否是一个零数组,如果是,则立即返回FALSE。

一个技术细节,在表达式左侧添加“(subsetundertest)&&&&”应该排除0的特殊情况。

也许我在这个问题中遗漏了一些东西,但是在这种情况下,你对子集的定义是什么?如果你对子集的定义是你认为的(从你的代码判断),那么你不应该用数组来打扰我们,你可能只是问我们如何判断一个int的'1'位是否是另一个int的'1'位的子集。@MikeNakis这正是我想要的,但要验证的位数不是恒定的(从~15到~100)。我曾想过使用两个长整数,但这比使用字节数组更困难…比我的代码好得多,但如果set_a是一个数组os zeros,它仍然会告诉我是真的。。。也许我在别的地方搞砸了?Giacomo是对的:如果set_a为零,您的解决方案将始终返回true。@Giacomo:但是,根据您的定义,missingno的解决方案是否正确还不清楚。通过严格阅读你的定义,他的解决方案是正确的。或者:当且仅当
a&b==a
。回答得好。。。有人知道如何修改它,使之成为一个严格的子集(即相等返回false)?
0 == ( a & ~b)
int is_subset (char *set_a, char *set_b, int size)
{
  int i;
  for (i = 0; i < size; i++){
    if(0 != (set_a[i] & (~ set_b[i])))
      return FALSE;
  }
  return TRUE;
}