【问题标题】:Python : arbitrary precision with floatsPython:带有浮点数的任意精度
【发布时间】:2017-07-25 07:22:12
【问题描述】:

我尝试计算 math.exp(9500),但遇到了 OverflowError: math range error(大约为 6.3e4125)。从this question 看来,这似乎是由于浮点数太大,接受的答案是“(...)略超出双精度范围,因此会导致溢出”。

我知道 Python 可以处理任意大的整数(long 类型),有没有办法以同样的方式处理任意大的浮点数?

编辑:我最初的问题是关于使用整数来计算 exp(n) 但正如 Eric Duminil 所说,最简单的方法是3**n,它没有提供任何有用的结果.我知道这个问题可能类似于this one

【问题讨论】:

  • 我什至不敢问什么样的问题需要计算exp(9500)...
  • 问题本身并没有,但我反复做矩阵乘法:A * B,但 B 加班变得更稀疏,A 保持不变。我试图根据 B 的稀疏性的变化来计算所需的乘法次数,在这种情况下,B 的“空”行的数量从 1 到 9500 以对数方式增长,这给了我们一个看起来有点像的乘法总数"从 1 到 n 的 i 总和 (A 行 * B 列 * ln( (exp(9500)/n) * i ))。
  • 在这种情况下,您可能应该简化公式:log((exp(9500)/n)*i)9500 + log(i/n),或 9500 + log(i) - log(n)。然后一切都将在正常的双精度浮点中工作。
  • @MarkDickinson 没错!我完全忘记了简化...我只是尝试过,Python 不再抱怨了。然而,同样的公式给我 3.7323287594132553 * 10^9 使用 Python 和 3.757328759413250...×10^9 使用 Wolfram Alpha。我想知道这是否只是一个舍入错误?
  • @potato:是的,只是一个舍入误差。

标签: python floating-point exponential bignum


【解决方案1】:

我认为不可能用整数来近似exp()。如果您使用3**n 而不是2.71828182845905**n,您的计算将完全没有用。

一种可能的解决方案是使用Sympy。根据文档:

基本上没有精度上限

>>> from sympy import *
>>> exp(9500)
exp(9500)
>>> exp(9500).evalf()
6.27448493490172e+4125

您还可以指定所需的精度:

>>> exp(9500).evalf(1000)
6.274484934901720177929867046175406311474380389941415760684209191232450360090766458256588885184199320756050569665785657269735313171886975309933254563488343491718198237894473901620914303565550450204805537225888529509352754121292701357622411614860860409639719786022989336837263283678476008817556351031696366815467221836948040042378034720460820127399855873232167818091083005170669482845098735176209372328114732133251096196535355946589133977397512846130629857604295369747597459602137604440011394793443041829253598478244189078131130488653468669559814695095974271938947640276013215753183113041899037415404445478806695965167014404297848725756879184380559837391976534521522360723388582608454995349380217499779247330557664230806254642768796486899322646423713763772064068933790640394967085887914192401473425799354391464743910233873602389444180426155866237536459654917521713769608318128404177877383203786348495822099924812081683286880293701785567962687838594752986160305764297117036426951203418854463404773701882e+4125

使用exp(9500).evalf(5000),您甚至可以获得最接近exp(9500) 的整数。

【讨论】:

  • 非常感谢,这正是我想要的。此外,您的解决方案提供了更多内容,而我的问题可能写得不太好,我重写了其中的一部分,使其更加精确和明确。
【解决方案2】:

这是用 Python 计算结果的另一种方法:

exp(9500)

太大了。

log10(exp(9500)) 不是。在 Python 中不能这样计算,但是log10(exp(9500))log(exp(9500))/ln(10),也就是9500/ln(10)

>>> from math import log
>>> 9500/log(10)
4125.797578080892
>>> int(9500/log(10))
4125
>>> 10**(9500/log(10) % 1)
6.274484934896202

这样,你可以计算出exp(9500)在纯Python中是6.27448493 * 10**4125,不需要任何库!

【讨论】:

    【解决方案3】:

    试试long 类型。

    int 类型自 3.0 版本以来已从 python 中删除。

    【讨论】:

    • 您应该在 cmets 中提供它而不是在答案中。阅读文档朋友@Mojann
    • 这是不正确的 - int 仍然在这里(尽管 long 可能更适合这个问题。)docs.python.org/3/library/stdtypes.html
    • 我问这个问题是因为math.exp 的结果是一个浮点数。 Python 已经在需要时将int 隐式转换为long
    • long 整数类型如何帮助计算 2.71828182845905**n
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多