这里的一个大问题是将二进制整数转换为十进制表示需要时间,其复杂度与位数成二次关系(至少在Python直接进行转换的方式中是如此)。实际上,像@6502在他的回答中所做的那样,伪造自己的十进制算术运算速度更快。
但是,让Python的decimal模块来处理它要快得多——至少在Python 3.3.2下是这样(我不知道Python decimal版本之前有多少C加速内置)。以下是代码:
class S:
def __init__(self):
import decimal
decimal.getcontext().prec = 4000
p2 = decimal.Decimal(1)
full = []
for i in range(10000):
s = "%s<%s>" % (p2, i)
full.append(s)
p2 *= 2
self.full = "".join(full)
def find(self, s):
import re
pat = s + "[^<>]*<(\d+)>"
m = re.search(pat, self.full)
if m:
return int(m.group(1))
else:
print(s, "not found!")
以及示例用法:
>>> s = S()
>>> s.find("1")
0
>>> s.find("2")
1
>>> s.find("3")
5
>>> s.find("65")
16
>>> s.find("7")
15
>>> s.find("00000")
1491
>>> s.find("666")
157
>>> s.find("666666")
2269
>>> s.find("66666666")
66666666 not found!
s.full
是一个具有超过1500万个字符的字符串。它看起来像这样:
>>> print(s.full[:20], "...", s.full[-20:])
1<0>2<1>4<2>8<3>16<4 ... 52396298354688<9999>
因此,该字符串包含每个2的幂,指数跟随在尖括号中的幂后面。 find()
方法构造一个正则表达式来搜索所需的子字符串,然后向前查找幂。
通过试验,我相信几乎任何搜索方式都足够快。获取大幂的十进制表示占用了绝大部分时间。而decimal
模块解决了这个问题。