python - 为什么第二个代码段比第一个运行得快得多?
问题描述
我对同一功能有两种不同的看法:
def is_prime(number):
for denominator in range(2, number):
if denominator ** 2 > number:
return True
if number % denominator == 0:
return False
return True
和
def is_prime(number):
denominator = 2
while denominator ** 2 <= number:
if number % denominator == 0:
return False
denominator += 1
return True
第一个代码块用于测试前 10**5 个数字大约需要 30 秒才能完成,第二个大约需要 350 毫秒。对于所有测试用例,两者都得出相同的答案。
为什么性能差异如此之大?
注意:这个怪癖不属于 ctypes 导入的测试性能,我知道 range(math.sqrt(number)) 更快,我们可以使用 Fermat 小定理使其更快。
解决方案
虽然片段 1 确实有更多的指令要执行,但两条if
语句只会使那些 if 语句的执行时间加倍(我在这里仅将其用作相对术语)。您的大部分速度都在for
循环中丢失:
python -m timeit -s 'i=0' 'for x in range(1000): i+=1'
10000 loops, best of 3: 46.4 usec per loop
python -m timeit -s 'i=0' 'while i<1000: i+=1'
10000 loops, best of 3: 0.0299 usec per loop
您在for
循环中损失了多个数量级,因此该if
语句相对无关紧要:
python -m timeit -s 'x=1; y=4' 'x<y'
10000000 loops, best of 3: 0.0256 usec per loop
但是,我要指出的是,python3range
和 python2就是这种情况xrange
。如果您使用的是 python2 range
,正如@jdowner 指出的那样,您将提前生成整个数字列表
推荐阅读
- admob - 更改 AdMob 基准国家/地区
- r - 理解为什么 sapply 在 R 中返回更长长度的向量
- sql - 使用动态 SQL 在一个参数中执行多列通配符搜索
- python-3.x - ec2client.describe_instances 在向 IAM 策略添加条件后返回 UnauthorizedOperation
- netsuite - Netsuite itemFulfillment search where status = Pick
- flutter - 如何用颤振罗盘找方向?
- android - 从 textView 获取 int
- haskell - 如何从每个可能的字符中生成字符串?
- reactjs - c.getBoundingClientRect 不是函数
- string - ESP8266 无法将字符添加到非常长的字符串(> 8000 个字符)