为什么在访问单个数字时,大整数除法比切片(数字)字符串更快?
我正在做一项(典型的)寻找素数的作业。我认为我会很聪明,对于大数,用这个技巧跳过除法过程:
def div5(candidate):
return str(candidate)[-1] == "5"
将 5 添加到自身几千次似乎是一种浪费(我只需要最后一个成员),但我想确定一下。
归功于unutbu Measure time elapsed in Python?
%>python -mtimeit -s"import intDiv" "intDiv.div5(2147483645)"
1000000 loops, best of 3: 0.272 usec per loop
%>python -mtimeit -s"import strDiv" "strDiv.str5(2147483645)"
1000000 loops, best of 3: 0.582 usec per loop
澄清一下,这是我定义的两个方法。
def div5(maxi): return not (maxi%5)
def str5(maxi): return str(maxi)[-1] == '5'
这太慢了。如何分析 str(maxi) 的最后一个成员,而不转换整个数字(不必要)?
感谢 @Claudiu 帮助清理了那些碍眼的东西。
I am doing a (typical) assignment of finding primes. I thought I'd be clever and, for large numbers, skip the division process with this trick:
def div5(candidate):
return str(candidate)[-1] == "5"
Adding 5 to itself a few thousand times seems like a waste (I only need the last member), but I wanted to be sure.
credit to unutbu on Measure time elapsed in Python?
%>python -mtimeit -s"import intDiv" "intDiv.div5(2147483645)"
1000000 loops, best of 3: 0.272 usec per loop
%>python -mtimeit -s"import strDiv" "strDiv.str5(2147483645)"
1000000 loops, best of 3: 0.582 usec per loop
For clarification, here are the two methods I defined.
def div5(maxi): return not (maxi%5)
def str5(maxi): return str(maxi)[-1] == '5'
This is too slow. How can I analyze the last member of str(maxi), without converting the whole number (needlessly)?
Thanks to @Claudiu for help with cleaning up the eyesores.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我想说瓶颈在于转换为字符串。
I'd say the bottleneck is converting to a string.
一个问题是将整数转换为字符串。这比整数除法要工作得多。
我不确定Python是如何做到这一点的,但大多数算法的工作原理都是这样的
,即每个
值
有多个模运算。One problem is the conversion of an integer to a string. This is much more work than doing integer division.
I am not sure how Python does it, but most algorithms work like
That is you have more than one modulo operation per
value
.将数字转换为字符串将如下所示:
您可以看到这将执行大量 % 操作(除了构建数字或字符串列表之外)。
除了这个优化问题之外,您的函数不正确。例如,10 不以 5 结尾,但可以被 5 整除。
Converting the number to a string will look something like this:
You can see this is going to do lots of % operations (aside from the construction of the list of digits or string).
Apart from this optimisation problem, your function isn't correct. For example, 10 doesn't end with 5, yet is divisible by 5.
您需要检查 5 和 0 是否能被 5 整除:
使用 6k±1 怎么样。如果该数字不能是素数,则返回 False。 2147483645%6 = 5 因此它可能是素数并且需要检查。此代码的运行时间比 div5 检查稍长一些,但您可以确定数字是否不能是素数。 3 以上的所有素数都符合序列 6k±1。所以 6(1)±1 = (5,7) 6(3)±1 = (17,19) 等等。模 6 都返回 5 或 1 作为余数。
我的 isPrime 适合小于 10**15 的数字。它还仅检查 sqrt(n) 并仅除以可能的素数。 for 循环将 p 和 q 设置为 5,7 11,13 17,19 23,25 29,31...
时间:
整个素数测试需要更长的时间:
You need to check 5 and 0 for divisible by 5:
How about using 6k±1. Return False if the number can't be a prime. 2147483645%6 = 5 so it could be prime and needs to be checked. This code runs for a little bit longer than the div5 check but you know for sure if a number cannot be prime. All primes above 3 fit into the sequence 6k±1. So 6(1)±1 = (5,7) 6(3)±1 = (17,19) and so on. modulus 6 all return either 5 or 1 as the remainder.
My isPrime for numbers less than 10**15. It also only checks up to sqrt(n) and only divides by possible primes. The for loop sets p and q to 5,7 11,13 17,19 23,25 29,31...
Times:
The whole prime test takes a bit longer: