计数步数达到0的功能

时间:2019-04-26 17:11:13

标签: python zero

我需要编写一个函数来计算达到零的总步数。规则是

  
      
  • 数字除以2
  •   
  • 然后减去1
  •   

例如,如果我有14号

  
      
  • 14/2 = 7
  •   
  • 7-1 = 6
  •   
  • 6/2 = 3
  •   
  • 3-1 = 2
  •   
  • 2/2 = 1
  •   
  • 1-1 = 0
  •   

总步数为6

请注意,输入x是二进制字符串:

def test(x):
    a = int(x,2)
    steps = 0
    while a != 0:
        if a % 2 == 0:
            a = a // 2  
        else:
            a = a - 1
        steps += 1
    return steps
test("1000")
Out[65]: 4

test("101")
Out[66]: 4

test("001")
Out[67]: 1

test("0010010001")
Out[68]: 10

test("001001")
Out[69]: 5

我需要知道有什么方法可以编写快速的函数吗?

3 个答案:

答案 0 :(得分:1)

假设您的代码正确且规则为:

  • test(0)= 0
  • test(n)= 1 + test(n / 2)如果n是偶数;
    1 + test(n − 1)否则

需要注意的重要一点是:

  • 偶数以二进制0结尾
  • 除以2会从末尾删除0(没有其他内容)
  • 奇数以二进制1结尾
  • 减去1将最后一个1变为0(没其他)

因此,除第一个比特外的每个1位增加2步,而每个有效比特0则增加1个步。这意味着对于以1开头的输入,您可以编写:

def test(x):
    return x.count('1') + len(x) - 1

现在,您只需要考虑前导零,或者如果无法使用前导零,则只需考虑"0"的特定情况。

答案 1 :(得分:0)

您的算法不适用于奇数。您只是在数字为偶数时进行除法,而这并不是您描述“步骤”的方式。

您想要的

def test(x, 2):
x_int = int(x)
steps = 0
while x_int <= 0:
    x_int //= 2
    x -= 1
    steps += 1

您应该阐明算法,因为描述方式不保证所有输入都收敛为0。您描述的方式是一个奇数无限循环。只需尝试1:

#test(1)
1 // 2 = 0
0 - 1 = -1
...

现在您永远都不会达到0,这就是为什么您应该检查x_int <= 0的原因。

我建议您重新考虑为什么要这样做。我可以肯定地说,您甚至不需要迭代算法就可以知道需要多少“步骤”,为此应该只有一个数学公式。

答案 2 :(得分:0)

您还可以使用递归方法:

def stepsToZero(N):
    return N if N < 2 else 2 + stepsToZero(N//2-1)

这将使您得到的结果达到N = 2 ** 993(这是一个很大的数字),并且功能非常简洁(imho更优雅)。

运行起来更快的是数学上的解决方法

例如:

import math
def steps2Zero(N):
    if N < 2: return N
    d = int(math.log(N+2,2))-1
    s = int(N >= 3*2**d-2)
    return 2*d+s

请注意,对于N = 2 ^ 900,数学解比递归快100倍。另一方面,递归函数在一秒钟内响应良好,并且可读性更高。因此,取决于使用方式和大小数字,性能考虑可能毫无意义