Python Decimal类型精度错误

2 投票
1 回答
901 浏览
提问于 2025-04-18 14:50

我遇到了一个很让人困惑的问题,我觉得可能和科学计数法以及小数精度有关。下面是我代码的一部分:

    def atan(x):
        # Calculate arctan(1/x)
        x = Decimal(x)
        current_value = Decimal(0)
        divisor = 1
        x_squared = x * x
        current_term = 1 / x


        while True:
            current_value += current_term

            divisor += 2
            current_term = (-current_term / x_squared) / divisor
            print(current_term)

            # The issue
            if current_term == Decimal(0):
                break

        return current_value

    print(atan(5))

这个是基于这个公式 atan(1/x) = 1/x - 1/(3x^3) + 1/(5x^5) - ...

但是,我发现 current_term 在每次循环中都变得越来越小,结果却出现了像 4E-80000 这样的值。因为我把小数精度 getcontext().prec 设置为 20,所以 current_term 不应该支持这些值。我觉得 current_term 可能不是小数类型,而是科学计数法或浮点数类型,但 Python 告诉我它仍然是小数类型。

对于 arctan(1/5),正确的值大约是 0.1973955。而我得到的值是 0.1973545,从第 5 位开始就不对了。即使我手动中断循环,值还是出错,不知道为什么。希望能有人帮我解决这个问题。

1 个回答

3

你的代码和公式不太一致。推导一个项到下一个项有点复杂了 ;-) 这里的 1/(5x^5) 项并不是 1/(3x^3) 项的倍数。

下面是直接模拟这个公式的代码:

from decimal import Decimal

def atan_recip(x):
    # Calculate arctan(1/x)
    x = Decimal(x)

    total = Decimal(0)
    sign = 1
    for i in range(1, 35, 2):
        total += sign / (i * x ** i)
        sign = -sign
        print(total)

atan_recip(5)

输出结果是你预期的:

0.2
0.1973333333333333333333333333
0.1973973333333333333333333333
0.1973955047619047619047619047
0.1973955616507936507936507936
0.1973955597889754689754689754
0.1973955598519908535908535908
0.1973955598498063202575202575
0.1973955598498834214339908457
0.1973955598498806620234645299
0.1973955598498807618878454823
0.1973955598498807582406246127
0.1973955598498807583748423407
0.1973955598498807583698713137
0.1973955598498807583700564416
0.1973955598498807583700495142
0.1973955598498807583700497745

撰写回答