我正在通过Project Euler问题学习python。对于 problem 40 我写了这段代码:
import math
i = 1
counter = 0
while counter <= 1000000:
MMM = int(math.log(i, 10)) + 1
counter = counter + MMM
V = math.log(i, 10)
print(i, counter, MMM, V)
i += 1
应该返回包含第N个数字的数字。基本上,这应该跟踪如果我将整数从1连接到另一个数字的情况会发生什么。目标是确定特定数字是什么。此代码在某个阈值以下工作,但是,当它达到百万位数时,它会被一个阈值关闭。我在这里错过了什么?我已经看到了其他节省时间的实现,但我更感兴趣的是为什么计数在某些时候出错了
编辑:
替换
MMM = int(math.log(i, 10)) + 1
与
MMM = len(str(i))
就像一个冠军!
虽然拥有一个全数字解决方案会很好,但它必须等到我可以信任Python中的日志函数。
答案 0 :(得分:4)
沿途的某处浮点错误?有可能在某个时刻math.log
返回的东西几乎不到(或者更大,取决于你的1次结果的方向)整数边界,因此int()
正在截断它错误的价值。对于无法使用一定数量的二进制数字表示的数字,浮点数不精确。
答案 1 :(得分:3)
我认为这是问题专栏
MMM = int(math.log(i, 10)) + 1
一些例子
>>> int(math.log(1000000, 10)) + 1
6
>>> int(math.log(1000001, 10)) + 1
7
我怀疑你真的想要
>>> len(str(1000000))
7
>>> len(str(1000001))
7
编辑实际上(正如您的建议!)math.log10似乎是最好的解决方案,更符合您最初的写作
>>> int(math.log10(10000000))
7
>>> int(math.log10(10000001))
7
>>> int(math.log10(10**1000))
1000
>>> int(math.log10(10**10000))
10000
>>> int(math.log10(10**100000))
100000
math.log10
必须保持准确性优于math.log(x, 10)
答案 2 :(得分:1)
这里的问题是浮点数的精度之一并不令人惊讶。随着数字位数的增加,我变得更模糊,更模糊。这是浮点数的基本特性,当你进行这种数学运算时,你需要知道你需要什么样的精度。
标准库模块decimal允许您对十进制值的精度进行精细控制。由于此模块不是硬件基础,允许用户改变浮点数的精度(默认为28位)。您创建如下的十进制数字:
import decimal
x = decimal.Decimal(1000000)
x.log10()
您可以改变所需的精度:decimal.getcontext().prec = 8