Pythonic方法计算尾随零的数量[重复]

时间:2021-10-03 22:54:35

This question already has an answer here:

这个问题在这里已有答案:

I'm looking for a Pythonic way to count the number of trailing zeros in the binary representation of a positive integer n (which will indicate the highest power of 2 which divides n without remainder).

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

A simple solution:

简单的解决方案:

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

But in order to do it in a more Pythonic manner, I think that I can make use of:

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

  • bin(n)[2:], which gives the binary representation of n
  • bin(n)[2:],给出n的二进制表示
  • bin(n)[:1:-1], which gives the reversed binary representation of n
  • bin(n)[:1:-1],它给出n的反向二进制表示

So my question can be reduced to counting the number of trailing zeros in a string.

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

Is there any single-statement way to do this?

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

My ultimate goal is a Pythonic way for computing the highest power of 2 which divides n without remainder, so any ways to do this not by counting the trailing zeros in a string are also appreciated.

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

4 个解决方案

#1


9  

You could use str.rstrip:

你可以使用str.rstrip:

def trailing(s):
    return len(s) - len(s.rstrip('0'))

#2


5  

This might do.

这可能会。

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

#3


1  

I'm not sure if this is the fastest solution, but it look like the most logical to me:

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

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

Since you asked for a single-line statement, here's one, but I don't think it's very legible (and its efficiency is worse than the other one):

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

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

#4


0  

Definitely use bit-pushing operations, if you are concerned specifically with the underlying binary representation of the number. Divide and modulo-divide are the most costly operations, and relate to arithmetic not hardware bits. So (untested code)

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

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"

If these integers might often be extremely large with very many trailing zeros (for cryptographical values of "large") it might make an important difference to efficiency to initialize test=1 and right-shift it one place every trip around the loop, rather than starting with 1 and shifting it po2 places.

如果这些整数可能通常非常大且有很多尾随零(对于“大”的密码值),那么初始化test = 1并将其每次绕行一次右移到效率可能会对效率产生重要影响,而不是从1开始并将它转移到po2位置。

#1


9  

You could use str.rstrip:

你可以使用str.rstrip:

def trailing(s):
    return len(s) - len(s.rstrip('0'))

#2


5  

This might do.

这可能会。

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

#3


1  

I'm not sure if this is the fastest solution, but it look like the most logical to me:

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

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

Since you asked for a single-line statement, here's one, but I don't think it's very legible (and its efficiency is worse than the other one):

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

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

#4


0  

Definitely use bit-pushing operations, if you are concerned specifically with the underlying binary representation of the number. Divide and modulo-divide are the most costly operations, and relate to arithmetic not hardware bits. So (untested code)

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

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"

If these integers might often be extremely large with very many trailing zeros (for cryptographical values of "large") it might make an important difference to efficiency to initialize test=1 and right-shift it one place every trip around the loop, rather than starting with 1 and shifting it po2 places.

如果这些整数可能通常非常大且有很多尾随零(对于“大”的密码值),那么初始化test = 1并将其每次绕行一次右移到效率可能会对效率产生重要影响,而不是从1开始并将它转移到po2位置。