我知道浮点数学的本质,但我仍然感到惊讶的是:
from fractions import Fraction
print(Fraction(0.2)) # -> 3602879701896397/18014398509481984
print(Fraction(str(0.2))) # -> 1/5
print(Fraction(0.2)==Fraction(str(0.2))) # returns False
print(0.2 == float(str(0.2))) # but this returns True!从文档上我找不到任何可以解释这一点的东西。它确实指出:
...In加法,任何表示有限值并被浮点构造函数接受的字符串也被分数构造函数接受.
但对我来说,这意味着类似于float()的行为,我只是没有看到如上面所示。
对此有什么解释吗?
需要注意的是,上面显示的行为并不是特定于值(0.2),而是一般的行为;我尝试过的一切都是这样的。
有趣的是:
from fractions import Fraction
for x in range(1, 257):
if Fraction(str(1/x))==Fraction(1/x):
print(x)只打印小于所选上限的2的幂:
1
2
4
8
16
32
64
128
256发布于 2018-02-09 13:59:39
如果给出一个字符串,请查看fractions.py中的fractions.py实现:
regex _RATIONAL_FORMAT (如果您对解析部分感兴趣,请参见链接)将numerator表示为0,decimal表示为2。
从fractions.py源开始引用,并附上我的评论
elif isinstance(numerator, str):
# Handle construction from strings.
m = _RATIONAL_FORMAT.match(numerator)
if m is None:
raise ValueError('Invalid literal for Fraction: %r' %
numerator)
numerator = int(m.group('num') or '0') # 0
denom = m.group('denom')
if denom: # not true for your case
denominator = int(denom)
else: # we are here
denominator = 1
decimal = m.group('decimal') # yep: 2
if decimal:
scale = 10**len(decimal) # thats 10^1
numerator = numerator * scale + int(decimal) # thats 0 * 10^1+0 = 10
denominator *= scale # thats 1*2
exp = m.group('exp')
if exp: # false
exp = int(exp)
if exp >= 0:
numerator *= 10**exp
else:
denominator *= 10**-exp
if m.group('sign') == '-': # false
numerator = -numerator
else:
raise TypeError("argument should be a string "
"or a Rational instance")出处报价
因此,'0.2'被精确地解析为2 / 10 = 0.2,而不是我的计算器在0,20000000000000001110223024625157上发布的最近的浮点近似。
经典:它们不仅仅是使用float( yourstring ),而是解析和计算字符串本身,这就是两者不同的原因。
如果使用相同的构造函数并提供float或decimal,则构造函数使用内置as_integer_ratio()获取分子和分母作为该数字的表示。
浮点表示最接近0.2的值是0,2000000000000000001110223024625157,这正是as_integer_ratio()方法返回命名子和分母的结果。
正如艾瑞克和马克·狄金森所指出的,这个浮点值被它的二进制表示限制为“接近0.2”。当被放入str()时,将被截断为精确的'0.2' -因此在
print(Fraction(0.2)) # -> 3602879701896397/18014398509481984
print(Fraction(str(0.2))) # -> 1/5发布于 2018-02-09 14:41:16
在print(Fraction(0.2))中,源文本0.2被转换为浮点值.此转换的结果正好是0.200000000000000011102230246251565404236316680908203125,或3602879701896397/18014398509481984。然后将这个值传递给Fraction,后者生成相同的值,表示为一个有理数。
在print(Fraction(str(0.2)))中,0.2再次转换为浮点值,从而得到上面的数字.然后str将其转换为字符串。在当前的Python版本中,当浮点值转换为字符串时,Python通常不会产生精确的数学值。相反,它会产生刚好足够的数字,以便将字符串转换为浮点,从而产生输入数字。在这种情况下,结果是“0.2”。所以字符串“0.2”被传递给Fraction。然后Fraction分析“0.2”并确定为1/5。
https://stackoverflow.com/questions/48707089
复制相似问题