我需要验证字节数组(即字符)中的位是否是同一类型的另一个数组的子集:例如,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;
}
但如果set_a
为零(0000.0000),则失败(始终返回TRUE)。我尝试了不同的策略(例如Bloom过滤器),但可能由于我的编程技巧,它远非快速或至少优雅。
有没有标准,优雅的方式做到这一点没有例外?
编辑:要明确,在此背景下&#34;子集&#34;表示第一个数组(set_a)中的所有位TRUE在第二个数组(set_b)中也为TRUE。第二个数组中可能还有其他位为TRUE,但如果它们在第一个数组中为FALSE则无关紧要。
答案 0 :(得分:5)
a
时, b
才是(a | b) == b
的子集。如果每个字节满足此条件,则返回TRUE
。否则返回FALSE
。
或等效(a & b) == a
。
答案 1 :(得分:4)
a
是b
的子集,a
中的每一位都隐含b
a -> b
或等效,
~a | b //not a or b
应该提供1111111
。
再次测试否定零可能更简单(检查是否存在我们在a中但未在b中设置位的情况)
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;
}
我不记得按位的东西是否适用于字符,或者你是否需要首先转换为无符号。
答案 2 :(得分:4)
我不确定你的代码是否失败是正确的,因为如果set_a是一个零数组,它返回TRUE,因为从纯粹的理论数学观点来看,空集是任何其他集合的子集。如果您不喜欢,那么您应该添加一个额外的检查以查看set_a是否为零数组,如果是,则立即返回FALSE。
答案 3 :(得分:0)
技术琐事,加上“(theSubsetUnderTest)&amp;&amp;”表达式左侧应排除0的特殊情况。