【问题标题】:Arithmetic precision problems with large numbers大数的算术精度问题
【发布时间】:2017-01-15 19:49:52
【问题描述】:

我正在编写一个程序来处理像10 ** 100 这样大的数字,在处理较小的数字时一切看起来都很好,但是当值变大时,我会遇到这些问题:

>>> N = 615839386751705599129552248800733595745824820450766179696019084949158872160074326065170966642688
>>> ((N + 63453534345) / sqrt(2)) == (N / sqrt(2))
>>> True

显然上面的比较是错误的,为什么会这样?

程序代码:

from math import *

def rec (n):
    r = sqrt (2)
    s = r + 2
    m = int (floor (n * r))
    j = int (floor (m / s))
    if j <= 1:
        return sum ([floor (r * i) for i in range (1, n + 1)])
    assert m >= s * j and j > 1, "Error: something went wrong"
    return m * (m + 1) / 2 - j * (j + 1) - rec (j)

print rec (1e100)

编辑:

我不认为我的问题与上面的链接问题重复,因为n, m and j 中的小数点对我来说并不重要,我正在寻找一种解决方案来避免这个精度问题。

【问题讨论】:

  • 浮点数的精度有限。如果标准范围不够,您必须使用编写自己的代码,也许使用像十进制这样的模块来帮助您。
  • Python 有任意精度的整数,但没有任意精度的实数。当您将NN + 63453534345 除以sqrt(2) 时,两者都被转换为IEEE double,它没有足够的精度来表示差异。
  • 有没有办法解决这个问题,我不关心小数,因为我最终需要这些数字?
  • 您需要计算 100 位数字的平方根吗?您还需要计算哪些其他操作?
  • 模块decimal 是更高(尽管显然仍然有限)精度的标准模块。

标签: python precision


【解决方案1】:

除以标准浮点数时,您无法保留所需的精度,因此您应该除以 Fractionfractions 模块中的 Fraction 类可让您进行精确的有理算术。

当然,2 的平方根不是有理数。但是如果错误小于10**100 的一部分,你会得到正确的结果。

那么,如何将sqrt(2) 的近似值计算为Fraction?有几种方法可以做到这一点,但一种简单的方法是计算2 * 10**200 的整数平方根,这将接近sqrt(2) * 10**100,然后将其作为分子并将10**100 作为分母。

这是 Python 3 中整数平方根的一个小程序。

def isqrt(n):
    lg = -1
    g = (1 >> n.bit_length() // 2) + 1
    while abs(lg - g) > 1:
        lg = g
        g = (g + n//g) // 2
    while g * g > n:
        g -= 1
    return g

你应该可以从那里拿走它。

【讨论】:

  • 很高兴我能帮上忙 :)
猜你喜欢
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2011-02-10
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多