python - 为什么提高精度会使这个程序更快?
问题描述
我正在解决 Project Euler 上的问题 26,我需要计算 1/n 的重复部分的长度,其中 n 是 1 到 1000 之间的所有整数,并查看哪个数字构成最长的重复部分。这意味着我需要更精确地完成我的部门。所以我通过改变来玩弄我的小数精度getContext().prec
,但后来不知何故提高了精度使程序快了很多。我使用 Python 3.7 运行了这个程序。这是代码:
import re
import time
s = time.time()
from decimal import *
getcontext().prec = 500 #This part
recurring = 0
answer = 0
p = re.compile(r"([0-9]+?)\1{3,}")
for i in range(1, 1000):
f = p.search(str(Decimal(1) / Decimal(i))[5:])
if f:
number = f.group(1)
if len(str(number)) > len(str(recurring)):
recurring = number
answer = i
print(answer)
print(time.time() - s)
这是我使用 500 精度时的结果:
>>> print(answer)
349
>>> print(time.time() - s)
2.923844575881958
...这就是我使用 5000 精度时得到的结果:
>>> print(answer)
983
>>> print(time.time() - s)
0.07812714576721191
我用 5000 交换了 500,它不仅给了我正确的答案,因为 1/answer 的重复部分可能比 500 长,而且速度也快得多。我已经使用在线 Python 解释器进行了尝试,它也给了我类似的结果。为什么会这样?
解决方案
它是正则表达式中 + 和 \1 的组合
方法
我使用了以下测试代码:
import time
import re
import string
t=time.time()
re.compile() # I tried differend regexes here
print(time.time()-t)
def test(n):
t=time.time()
match = rex.search(string.ascii_lowercase*n)
print(match, time.time()-t)
重新启动 python 会话后,第一次调用re.compile
比后续编译相同的正则表达式花费的时间更长。
compile(sec) search (sec)
REGEX 1st 2nd short long string
r"(abcdefghijklmnopqrstuvwxyz){6,}" 10^-4 10^-5 10^-5 10^-5
r"(abcdefghijklmnopqrstuvwxyz)\1\1\1\1" 10^-4 10^-5 10^-6 10^-6
r"([a-z]+?)\1\1\1\1" 10^-4 10^-5 10^-4 10^-5
r"([a-z]+)\1\1\1\1" 10^-4 10^-5 10^-4 10^-5
r"([a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z][a-z])\1\1\1\1"
10^-4 10^-5 10^-6 10^-6
r"([a-z]+?)\1\1\1"
有趣的是,对于太短的字符串,偶尔也会很快(10^-5 秒)。
讨论
编译 rexex 涉及到一些缓存,但这不是这里的原因。
似乎+
组内的运算符(贪婪和非贪婪)和\1
正则表达式中的组合是错误的。出于某种原因,如果实际匹配,则此组合比不匹配时更快。
要了解更多,我们可能要了解sre
模块的 C 源代码
推荐阅读
- c# - 只要在文本框中单击用户,有没有办法使工具提示保持可见?
- python - 如果不是绝对必要的,是否应该使用临时(非成员)变量?
- apache-kafka - 删除重复项(将键视为航班号)并仅获取最新记录 wrt 时间戳
- python - 如何在我的 python 计算器上制作平方根按钮(我是初学者)
- python-3.x - 无法将空列表保存到 Django ArrayField
- php - 检查字符串是否包含两个单词或PHP中带有下划线的特殊字符
- go - 运行 Go exec.Command() 的 Visual Studio Code 因“kubectl 版本”而超时
- c++ - c++ 中是否有一个函数允许我在屏幕上呈现文本,该文本将保持在窗口模式下的任何程序前面?
- reactjs - Babel-loader:意外的令牌
- angular - 如何创建简单的导航测试用例 - Karma Testing Angular