模数和 FizzBuzz 的计算复杂度
Computational complexity of modulos and FizzBuzz
所以我不想讨论这是否是 FizzBuzz 挑战的最完美代码。
对于那些不熟悉 FizzBuzz 的人,打印出 1-100 的 运行ge 有四个规则:
- 打印出所有数字;
- 如果数字能被3整除,打印"Fizz";
- 如果数字能被5整除,打印"Buzz";
- 如果号码是
被 3 和 5 整除,打印 "FizzBuzz".)
我运行两种实现方式,比较它们的速度:
# Code A
%%timeit
for i in range(1,10001):
if i % 15 == 0:
print('FizzBuzz')
elif i % 3 == 0:
print('Fizz')
elif i % 5 == 0:
print('Buzz')
else:
print(i)
# Code B
%%timeit
for i in range(1,10001):
if i % 5 == 0 and i % 3 == 0:
print('FizzBuzz')
elif i % 3 == 0:
print('Fizz')
elif i % 5 == 0:
print('Buzz')
else:
print(i)
尽管对代码 B 进行了额外的 if
评估,但它始终 运行 比代码 A 更快。更大的数字会导致更慢的模数吗?这背后的根本原因是什么?
我能想到的主要原因可能是优化。
版本B多次使用相同的操作,即:
- 我mod5
- 我mod3
相当聪明的 compiler/interpreter 可能会发现这一点,并计算出这些中间结果。这样一来,只需 2 mod 次操作即可立即计算出整个 if 块。
简而言之,我认为最终执行的代码可能如下所示:
for i in range(1,10001):
a = i % 5
b = i % 3
if a == 0 and b == 0:
print('FizzBuzz')
elif b == 0:
print('Fizz')
elif a == 0:
print('Buzz')
else:
print(i)
不过,A块的代码可能太复杂了。也就是说,我的意思是编译器将始终被迫执行 3 mod 操作。除非它能以某种方式发现 15 = 3 * 5,并使用该逻辑重新处理 if 语句。
所以我不想讨论这是否是 FizzBuzz 挑战的最完美代码。
对于那些不熟悉 FizzBuzz 的人,打印出 1-100 的 运行ge 有四个规则:
- 打印出所有数字;
- 如果数字能被3整除,打印"Fizz";
- 如果数字能被5整除,打印"Buzz";
- 如果号码是 被 3 和 5 整除,打印 "FizzBuzz".)
我运行两种实现方式,比较它们的速度:
# Code A
%%timeit
for i in range(1,10001):
if i % 15 == 0:
print('FizzBuzz')
elif i % 3 == 0:
print('Fizz')
elif i % 5 == 0:
print('Buzz')
else:
print(i)
# Code B
%%timeit
for i in range(1,10001):
if i % 5 == 0 and i % 3 == 0:
print('FizzBuzz')
elif i % 3 == 0:
print('Fizz')
elif i % 5 == 0:
print('Buzz')
else:
print(i)
尽管对代码 B 进行了额外的 if
评估,但它始终 运行 比代码 A 更快。更大的数字会导致更慢的模数吗?这背后的根本原因是什么?
我能想到的主要原因可能是优化。
版本B多次使用相同的操作,即:
- 我mod5
- 我mod3
相当聪明的 compiler/interpreter 可能会发现这一点,并计算出这些中间结果。这样一来,只需 2 mod 次操作即可立即计算出整个 if 块。
简而言之,我认为最终执行的代码可能如下所示:
for i in range(1,10001):
a = i % 5
b = i % 3
if a == 0 and b == 0:
print('FizzBuzz')
elif b == 0:
print('Fizz')
elif a == 0:
print('Buzz')
else:
print(i)
不过,A块的代码可能太复杂了。也就是说,我的意思是编译器将始终被迫执行 3 mod 操作。除非它能以某种方式发现 15 = 3 * 5,并使用该逻辑重新处理 if 语句。