检查所有位是否为 1 的最佳方法是什么?

What is the best way to check if all bits are 1?

由于 ~,我认为这很容易,但是 ~ 只是 returns 负值 2^x 而不是 0。

最简单的方法是检查 0 是否出现在 bin(n) 中。以下是一些示例:

全 1 的数字:

>>> n=15
>>> bin(n)
'0b1111'
>>> bin(n)[2:]
'1111'
>>> '0' in bin(n)[2:]
False

有 1 个或多个 0 的数字:

>>> n=5
>>> bin(n)
'0b101'
>>> bin(n)[2:]
'101'
>>> '0' in bin(n)[2:]
True

您可以修改标准 bithack 来检查数字是否为 2 的幂(小于 2 的幂的数字均为 1),特殊情况检查为零:

def allOnes(n):
    return ((n+1) & n == 0) and (n!=0)

print allOnes(255)
print allOnes(158)
print allOnes(0)
print allOnes(-1)
print allOnes(-2)

输出:

True
False
False
True
False

大多数语言使用 MSB(最高有效位)作为有符号值位。例如,二进制的 00000001 是十进制的 1,二进制的 10000011 是十进制的 -125(因为 MSB 是 1 (-128) & 00000011 是十进制的 3 (-128 + 3 = -125))。

因此所有位都是1的二进制数在十进制中相当于-1。 所以简单地说,如果 byte_value 是一个带符号的整数,

if(byte_value = -1)
{
    printf("All One's");
}
else
{
    printf("All Not One's");
}

否则

if(byte_value = 255)
{
    printf("All One's");
}
else
{
    printf("All Not One's");
}

您可能需要的是 XOR (^) 运算符,而不是您尝试过的按位非 (~) 运算符(因为它只会还原每一位)。由于您提到 ~ 运算符作为您的初始方法,我假设您想通过与全 1 的整数进行比较来确定整数中的所有位是否为 1。也许您正在优化速度。

异或运算符 return 仅当操作数中的任一位为 1 时才为 1。因此,只要任何位为 0,它都会给出 1。

>>> 100 ^ 000
100
>>> 100 ^ 100
0
>>> 111 ^ 101
10
>>> 111 ^ 111
0

(如您所见,结果整数未被填充,但这对我们的目的无关紧要。)

唯一'gotcha'就是你需要提前知道你的号码的位数

然后您可以通过查看结果数字是否大于 0 来检查其中的所有位是否都是 1。如果是,那么您就知道并非所有位都是 1。

示例:

只要 someNumberWithThreeBits 中的所有位都为 1,

someNumberWithThreeBits ^ 111 == 0 将 return 为真,否则为假。

PS:请注意 000 ^ 000 也会 return 0。但是在这种情况下您不会遇到这种情况,除非您决定与 000 而不是 111 进行比较。

基于@samgak 对@Martjin Pieters 关于特定整数大小的评论的回应,如果要求特定大小的所有位都是 1,那么我们的测试需要修改。想象一下,例如,我们要测试一个 nibble 大小的整数在二进制表示中是否全为 1:

In [2]: def all_ones_nibble(to_test: int) -> bool:
   ...:     assert 0 <= to_test < (1 << 4)
   ...:     # bin(1 << 4) == "0b10000", therefore bin((1 << 4) - 1) == "0b1111"
   ...:     return to_test == (1 << 4) - 1
   ...:

In [3]: all_ones_nibble(int("0", base=2))
Out[3]: False

In [4]: all_ones_nibble(int("1", base=2))
Out[4]: False

In [5]: all_ones_nibble(int("1111", base=2))
Out[5]: True

当然,将自己限制在半字节有点愚蠢,所以让我们概括为任意大小:

In [6]: def all_ones_for_size(to_test: int, size: int) -> bool:
   ...:     return to_test == (1 << size) - 1
   ...:

In [7]: all_ones_for_size(int("1111", base=2), 4)
Out[7]: True

In [8]: all_ones_for_size(int("11111111", base=2), 8)
Out[8]: True

In [9]: all_ones_for_size(int("11111110", base=2), 8)
Out[9]: False

最后,为了好玩,让我们使用@riteshtch 的技术来获得相同的结果:

In [10]: def all_ones_for_size_using_strs(to_test: int, size: int) -> bool:
    ...:     # NOTE: using a format string obviates the need to shave off "0b".
    ...:     # For example, f"{int('1111', base=2):b}" == "1111", whereas
    ...:     # bin(int("1111", base=2)) == "0b1111"
    ...:     as_bin_str = f"{to_test:b}"
    ...:     return len(as_bin_str) == size and not "0" in as_bin_str
    ...:

In [11]: all_ones_for_size_using_strs(int("11111110", base=2), 8)
Out[11]: False

In [12]: all_ones_for_size_using_strs(int("11111111", base=2), 8)
Out[12]: True

In [13]: all_ones_for_size_using_strs(int("1111", base=2), 8)
Out[13]: False

请注意,此答案使用 python 3 和 type annotations,这不适用于 python 2.7,但因为 python 2 已经 long-since日落,充满希望的未来观众会发现现代代码更有用。