在这个时间复杂度计算中我哪里出错了?

时间:2017-06-13 15:35:08

标签: python time-complexity

我在Python中有这个功能:

digit_sum = 0
while number > 0:
   digit_sum += (number % 10)
   number = number // 10

为了确定时间复杂度,我应用了以下逻辑:

第1行: 1个基本操作(分配),执行1次,因此获取值 1

第2行: 2个基本操作(读取变量'number'并与零比较),执行n + 1次,因此得到 2 *(n + 1)的值

第3行: 4个基本操作(读取变量'number',%10,计算总和和赋值),执行n次,得到值 4 * n

第4行: 3个基本操作(读取变量'number',// 10和赋值),执行n次,因此获得值 3 * n

这让我总共 1 + 2n + 2 + 4n + 3n = 9N + 3

但我的教科书有 8n + 3 的解决方案。我的逻辑在哪里出错?

谢谢,

亚历

1 个答案:

答案 0 :(得分:2)

在谈论复杂性时,你真正关心的是asymptotic complexity。这里, O(n)。 8或9或42并不重要,特别是因为没有办法让你知道。

因此计算"操作"毫无意义。它暴露了底层处理器的架构细节(无论是实际的hw proc还是解释器)。真正获得真实"的唯一途径操作次数将是查看特定的实现(例如,比如CPython 3.6.0),并查看它从您的程序生成的字节码。

这是我的CPython 2.7.12所做的:

>>> def test(number):
...     digit_sum = 0
...     while number > 0:
...         digit_sum += (number % 10)
...         number = number // 10
...
>>> import dis
>>> dis.dis(test)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               1 (digit_sum)

  3           6 SETUP_LOOP              40 (to 49)
        >>    9 LOAD_FAST                0 (number)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       48

  4          21 LOAD_FAST                1 (digit_sum)
             24 LOAD_FAST                0 (number)
             27 LOAD_CONST               2 (10)
             30 BINARY_MODULO
             31 INPLACE_ADD
             32 STORE_FAST               1 (digit_sum)

  5          35 LOAD_FAST                0 (number)
             38 LOAD_CONST               2 (10)
             41 BINARY_FLOOR_DIVIDE
             42 STORE_FAST               0 (number)
             45 JUMP_ABSOLUTE            9
        >>   48 POP_BLOCK
        >>   49 LOAD_CONST               0 (None)
             52 RETURN_VALUE

我让你得出自己想要实际算作基本操作的结论。 Python解释器一个接一个地解释字节码,所以可以说你有15"基本操作"在你的循环中。这是你能得到一个有意义的数字的最接近的。尽管如此,那里的每个操作都有不同的运行时间,因此15没有任何有价值的信息。

另外,请记住这是CPython 2.7.12特有的。很可能另一个版本会生成其他版本,利用新的字节码可能会以更简单的方式表达某些操作。