用于计算尾随零的数量的Pythonic方法

时间:2016-11-15 11:04:23

标签: python

我正在寻找一种Pythonic方法来计算正整数n的二进制表示中的尾随零的数量(这将表示2除以n的最高幂没有余数)。

一个简单的解决方案:

def CountZeros(n):
    c = 0
    while (n % 2) == 0:
        n /= 2
        c += 1
    return c

但是为了以更加Pythonic的方式做到这一点,我认为我可以利用:

  • bin(n)[2:],它提供n
  • 的二进制表示
  • bin(n)[:1:-1],它提供n
  • 的反向二进制表示

所以我的问题可以简化为计算字符串中尾随零的数量。

有没有单一陈述方式可以做到这一点?

我的最终目标是用于计算2的最高幂的Pythonic方法,它将n除以余数,因此任何方法都不是通过计算字符串中的尾随零来实现这一点。

5 个答案:

答案 0 :(得分:9)

您可以使用- (CGAffineTransform)targetTransform { return CGAffineTransformIdentity; }

str.rstrip

答案 1 :(得分:5)

这可能会。

def trailing_zeros(n):
    s = str(n)
    return len(s)-len(s.rstrip('0'))

答案 2 :(得分:1)

我不确定这是否是最快的解决方案,但它看起来对我来说最合乎逻辑:

def trailing_zeros(n):
    for i in range(20):
        if n % (2<<i) != 0:
            return i

既然你要求单行声明,这是一个,但我不认为它非常清晰(而且它的效率比另一个更差):

max(i+1 for i in range(20) if n%(2<<i) == 0)

答案 3 :(得分:1)

避免使用bin转换为字符串,而使用修改后的bithack,因为我们已经有一个高效的log2实现,所以它的速度快两倍。

def ctz(v):
    return (v & -v).bit_length() - 1

如果输入为0,则上面的代码返回-1。

使用C使其速度再次提高一倍:

from gmpy2 import bit_scan1 as ctz

如果输入为零,此版本将返回None。


例如,如果输入为20,则考虑无限二进制扩展:

v    000...00010100
~v   111...11101011 (not used directly, all bits opposite)
-v   111...11101100 (-v == ~v + 1; this causes all low 1 bits to overflow and carry)
v&-v 000...00000100 (has a single 1 bit, from the carry)

and被加完后,所有前导零和一位都是相反的,但是最后一位和所有尾随零都是相同的。

然后.bit_length()告诉我们,整数总共使用3位,因此只需减去1即可考虑零。

答案 4 :(得分:0)

如果您特别关注数字的基础二进制表示,那么绝对使用位推操作。除法和模除法是最昂贵的操作,并且与算术而不是硬件位相关。所以(未经测试的代码)

def fnzb( n):
    " return position of first non-zero bit in n"
    if n==0:
        # edge case, there ARE no nonzero bits
        return None
    for po2 in range(0, 128) # or whatever larger upper limit is desired
        if a & ( 1 << po2) != 0: return po2
    # edge case, n too large
    raise ValueError,  "'impossibly' large integer argument encountered"

如果这些整数通常非常大且有很多尾随零(对于“大”的密码值),可能可能对初始化test=1和右 - 的效率产生重大影响

在每个行程中将其移动一个位置,而不是从1开始并将其移动po2个位置。