提问人:ONLYA 提问时间:3/4/2023 更新时间:3/4/2023 访问量:123
解释器和脚本中的 Python 精确数学计算,无需一直键入十进制模块
Python precision math calculation in interpreter and script without typing decimal module all the time
问:
我注意到 python 中的数学运算不像以前那么精确,尤其是涉及浮点数的运算。我知道这是由于二进制数表示的性质,我们可以通过执行以下操作来解决这个问题:
from decimal import Decimal
a = Decimal('0.1') + Decimal('0.2')
我甚至可以做一些进一步的事情,比如:
def func(a, b, operator):
a_ = Decimal('{}'.format(a))
b_ = Decimal('{}'.format(b))
return eval('float(a_ {} b_)'.format(operator))
func(0.1, 0.2, '+') # will return 0.3
但是,我不想走到这一步。事实上,我一直在使用 python 作为计算器或 Matlab 替代品。为了快速计算而必须编写更多的东西并不方便。decimal 模块的上下文设置还要求在数字前面写上“Decimal”。
这个 5 年前的问题集中在脚本上,而不是在口译员内部工作。我也尝试了代码示例,但它没有按预期工作。
有没有一种快速而肮脏的方法可以使python执行具有相同的结果?
它也应该应用于其他数学运算,如等式比较。0.1 + 0.2
float(Decimal('0.1') + Decimal('0.2'))
**
==
答:
0赞
Alan
3/4/2023
#1
一种方法是创建一个名为 (for decimal) 的新对象类型。D
from decimal import Decimal
class D:
def __init__(self, d: float | int):
self.d = Decimal(str(d))
def __add__(self, other_d: D):
return self.d + other_d.d
通过覆盖 上的方法,可以重新创建所需的加法行为。同样,您可以覆盖与每个算术运算符对应的魔术方法。(例如,覆盖 等)__add__
D
__eq__
==
一旦到位,你可以做一些事情,比如:
a = D(0.1)
b = D(0.3)
c = a + b
print(c)
-> 0.4 (Decimal type)
评论
0赞
Alan
3/4/2023
请注意,参数(例如 、 和 )的键入取决于 python 版本。如果它们出现错误,只需将其删除即可。d: float | int
other_d: D
0赞
jodag
3/4/2023
这似乎并不比仅仅使用D=Decimal
0赞
ONLYA
3/4/2023
在新类中使用内部方法是一个很好的方法。但是,有没有办法将 python 将浮点文字解释为 Decimal 类字符串输入的方式?结果,在做了一系列事情之后,我就可以输入,这将返回0.3?0.1+0.2
0赞
Alan
3/4/2023
@ONLYA这是一个有趣的问题,这里回答了一个相关的问题:stackoverflow.com/a/7880276/12705481。要点归结为抽象语法树;这些是将编写的 Python 代码存储为编译器指令序列的数据结构。您可以通过标准库模块与它们进行交互。也许有一种方法可以做你想做的事情,尽管如果有的话,它是非常基本和棘手的事情(当然超出了我的理解!我的解决方案至少提供了一个速记。ast
0赞
Alan
3/4/2023
@jodag优点是字符串转换。如果这样做,则会出现舍入错误。因此,您必须避免舍入错误。这个解决方案让我们更接近于使用“原始”浮点数。Decimal(0.1)
Decimal("0.1")
评论
0.1+0.2
0.3000000000000000444089209850062616169452667236328125
fprintf('%.52f',0.1+0.2)