📌  相关文章
📜  下一个比N大的数字,N的二进制表示形式仅相差一位(1)

📅  最后修改于: 2023-12-03 14:48:48.610000             🧑  作者: Mango

下一个比N大的数字,N的二进制表示形式仅相差一位

当我们需要寻找一个比给定数字N大的数字,并且要求该数字的二进制表示与N只相差一位时,我们该如何实现?这里提供两种解决方案:位运算和数学方法。

位运算

我们可以通过位运算,对N进行一系列的操作,得到比N大且二进制表示只有一位不同的数。

首先,我们需要找到N中最右侧的一个0,记其所在位置为p。然后,将N的第p个二进制位取反得到的数为k。最后,我们将k加到N上,即可得到符合条件的下一个数字。

def next_num(n):
    p = 0
    while ((n >> p) & 1) != 0:
        p += 1
    n ^= (1 << p) # 反转第p个二进制位
    n += 1
    return n

以上代码便是利用位运算来实现查找下一个比N大的数字,并且二进制表示仅相差一位。

数学方法

另一种实现方式是利用数学思想,得到一个 closed-form expression(解析解)。

记所求数字为x,其二进制表示为: $$ x = a_0 + 2a_1 + 2^2a_2 + ... + 2^k a_k $$ 其中 $a_i$ 表示 $x$ 的第 $i$ 位二进制数值。

我们考虑到 $x$ 的下一个相差一位的数是不同的,所以必然有某个 $i$ 满足 $a_i = 0$,$a_{i+1} = 1$。我们要找到一个公式,通过 $a_0 ... a_{i−1}$ 快速计算 $x$。

该公式为: $$ x = (y + 1)2^{i+1} - 1 $$ 其中 $y$ 表示 $x$ 的前 $i$ 位二进制数值,可以通过以下公式得到: $$ y = \frac{x}{2^{i+1}} - 1 $$

def next_num(n):
    y = n
    c0 = 0
    c1 = 0
    
    while (y & 1) == 0 and y != 0:
        c0 += 1
        y >>= 1
    
    while (y & 1) == 1:
        c1 += 1
        y >>= 1
    
    if c0 + c1 == 31 or c0 + c1 == 0: # 错误检测,保证算式中的位数均小于32
        return -1
    
    p = c0 + c1 # 反转第p个二进制位
    n |= (1 << p)
    n &= ~((1 << p) - 1)
    n |= (1 << (c1 - 1)) - 1
    
    return n

以上是数学方法的实现代码。

两种方法均可解决这个问题,读者可根据实际场景选择不同的方法。