Python 3位小数模计算可逆性
Python 3 decimal module calculation reversability
我正在尝试实现一个可逆物理引擎,所以我决定使用 decimal 模块。所以这显然有效。
>>> from decimal import *
>>> a = Decimal('1')
>>> b = Decimal('0.82')
>>> a = a*b/b
>>> print(a)
1
但是,当重复这个操作时,即"multiply 100 times and then divide 100 times",结果并不完全等于a
。
>>> for _ in range(100):
... a = a*b
...
>>> for _ in range(100):
... a = a/b
...
>>> a
Decimal('0.9999999999999999999999999965')
我是不是做错了什么?是否可以逆向进行这些计算,以便得到初始结果?
小数没有无限精度。如果您觉得它太不准确,您可以increase its precision。
from decimal import *
getcontext().prec = some larger number
您可以改用分数模块:
>>> from fractions import Fraction
>>> a = Fraction(1)
>>> b = Fraction(82, 100)
>>> for _ in range(100):
... a *= b
...
>>> a
Fraction(189839102486063226543090986563273122284619337618944664609359292215966165735102377674211649585188827411673346619890309129617784863285653302296666895356073140724001, 78886090522101180541172856528278622967320643510902300477027893066406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
>>> for _ in range(100):
... a /= b
...
>>> a
Fraction(1, 1)
您还可以利用 Python 实现的无限大整数,方法是将所需的十进制数设为整数,而不是将它们全部乘以一个足够大的因子,然后将结果除以相同的因子:
a = 100 # 1 times a factor of 100
b = 82 # 0.82 times a factor of 100
for _ in range(100):
a = a*b
for _ in range(100):
a = a//b
print(a)
这输出:
100 # divide this by a factor of 100 to get back 1
我正在尝试实现一个可逆物理引擎,所以我决定使用 decimal 模块。所以这显然有效。
>>> from decimal import *
>>> a = Decimal('1')
>>> b = Decimal('0.82')
>>> a = a*b/b
>>> print(a)
1
但是,当重复这个操作时,即"multiply 100 times and then divide 100 times",结果并不完全等于a
。
>>> for _ in range(100):
... a = a*b
...
>>> for _ in range(100):
... a = a/b
...
>>> a
Decimal('0.9999999999999999999999999965')
我是不是做错了什么?是否可以逆向进行这些计算,以便得到初始结果?
小数没有无限精度。如果您觉得它太不准确,您可以increase its precision。
from decimal import *
getcontext().prec = some larger number
您可以改用分数模块:
>>> from fractions import Fraction
>>> a = Fraction(1)
>>> b = Fraction(82, 100)
>>> for _ in range(100):
... a *= b
...
>>> a
Fraction(189839102486063226543090986563273122284619337618944664609359292215966165735102377674211649585188827411673346619890309129617784863285653302296666895356073140724001, 78886090522101180541172856528278622967320643510902300477027893066406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
>>> for _ in range(100):
... a /= b
...
>>> a
Fraction(1, 1)
您还可以利用 Python 实现的无限大整数,方法是将所需的十进制数设为整数,而不是将它们全部乘以一个足够大的因子,然后将结果除以相同的因子:
a = 100 # 1 times a factor of 100
b = 82 # 0.82 times a factor of 100
for _ in range(100):
a = a*b
for _ in range(100):
a = a//b
print(a)
这输出:
100 # divide this by a factor of 100 to get back 1