📜  计算范围内的设置位(1)

📅  最后修改于: 2023-12-03 15:41:41.723000             🧑  作者: Mango

计算范围内的设置位

在程序设计中,经常需要判断一个数的二进制表示中哪些位是设置为1的。本文将介绍如何计算一个数在指定范围内的设置位。

思路

假设有一个数 $num$,它的二进制表示为 $b_0b_1b_2\dots b_{n-1}$,其中 $b_i$ 表示二进制中从右边往左数第 $i$ 位的值($i$ 从0开始),$n$ 表示二进制的位数。现在需要计算 $num$ 在指定范围 $[l, r]$ 内的设置位。

首先,我们需要把二进制数 $num$ 中的第 $l$ 位到第 $r$ 位的数值保留,其余位上都设置为0。可以使用一个长度为 $n$ 的二进制数,将第 $l$ 位到第 $r$ 位上都设置为1,其余位上都设置为0,然后与 $num$ 进行按位与操作。这样就得到了指定范围内的数值。例如,下面的代码可以计算 $num$ 在第 2 位到第 4 位内的数值。

mask = int('1110', 2)   # mask的二进制表示为1110
result = num & mask

接着,我们可以把结果向右移动 $l$ 位,使它的二进制表示从右往左数第 $l$ 位变成了第0位,从而方便后续的计算。例如,如果在上面的例子中计算得到的数值为 $1010$,则将其向右移动2位后得到 $10$。

最后,我们可以通过不断地将结果分解为2的幂次和的方式,判断二进制中哪些位是设置为1的。例如,如果得到的结果为 $10$(二进制为 $1010$),它可以表示为 $2^1 + 2^3$ 的和,即第 1 和第 3 位上是设置为1的。

具体实现细节可以参考下面的代码。

代码实现
def get_set_bits(num: int, l: int, r: int):
    # 保留[l:r]范围内的数值
    mask = (1 << (r - l + 1)) - 1   # 全1的二进制数
    mask <<= l   # 左移l位
    result = num & mask

    # 右移l位
    result >>= l

    # 计算设置位
    set_bits = []
    bit_pos = 0
    while result > 0:
        if result & 1 == 1:
            set_bits.append(l + bit_pos)
        result >>= 1
        bit_pos += 1

    return set_bits

代码中的 get_set_bits 函数接受三个参数:num 表示要计算的数,lr 表示要计算的范围。函数返回一个列表,其中存放了[l, r]范围内的设置位。例如,如果要计算数值 38 在第 2 位到第 4 位内的设置位,可以调用这个函数:

>>> get_set_bits(38, 2, 4)
[2, 4]

这个结果表明数值 38 的二进制表示中,第 2 和第 4 位上是设置为1的。