在Python中处理非常小的数字

use*_*780 7 python math decimal underflow

我需要乘以1e6数量级为的数字0.01。预期结果是有序的1e-100000000。显然,典型的浮点算法无法处理此问题。

在网络上进行了一些研究,我发现了十进制库,似乎可以解决此问题。但是,它似乎有局限性,无法满足我的需求:

>>> Decimal('.01')**Decimal('1e5') # Seems to handle this
Decimal('1E-200000')
>>> Decimal('.01')**Decimal('1e5')*Decimal('1E200000') # Yeah! It works!
Decimal('1')
>>> Decimal('.01')**Decimal('1e6') # This result is strange...
Decimal('0E-1000026')
>>> Decimal('.01')**Decimal('1e6')*Decimal('0E1000026') # Wrong result
Decimal('0')
Run Code Online (Sandbox Code Playgroud)

有谁知道解决方案吗?

ing*_*var 5

您的结果不正确,因为小数也有精度(小数是定点数学),因此您也会在这里遇到下溢问题:

Decimal('.01')**Decimal('1e6')
Run Code Online (Sandbox Code Playgroud)

十进制('0E-1000026')

但:

getcontext().prec = 1000000000   # sets precision to 1000000000
Decimal('.01')**Decimal('1e6')
Run Code Online (Sandbox Code Playgroud)

十进制('1E-2000000')

您可以通过手动设置精度(如上例所示)或手动计算功效来解决问题,例如:

Decimal('.01')**Decimal('1e6')
Run Code Online (Sandbox Code Playgroud)

可以转换为

Decimal('1e-2') ** Decimal('1e6')
Run Code Online (Sandbox Code Playgroud)

然后到

1 ** ((-2) ** 1e6) = 1 ** (-2000000)
Run Code Online (Sandbox Code Playgroud)

十进制模块文档