2016-07-03 23 views
3

在Python 3.52的float类型转换为分数类型转换时,我发现了两种不同的转换方式之间的区别。在Python中浮点到分数的转换

第一种方法是:

>>> from fractions import Fraction 
>>> x = 1232.23 
>>> f = Fraction(*x.as_integer_ratio()) 
>>> print(f) 
2709702426188841/2199023255552  #Answer 

第二种方法是:

>>> from fractions import Fraction 
>>> x = 1232.23 
>>> f = Fraction(str(x)) 
>>> print(f) 
123223/100       #Answer 

我想知道这两个不同的答案背后的原因是什么?对不起,如果这是一个愚蠢的问题,我是编程和Python的新手。

编辑:我发现了一种通过limit_denominator方法,通过第一种方法来准确获得不准确的分数转换:

>>> from fractions import Fraction 
>>> x = 1232.23 
>>> f = Fraction(*x.as_integer_ratio()) 
>>> f = f.limit_denominator(100)  
>>> print(f) 
123223/100 

回答

4

又是因为浮点数不是以base-10(十进制)存储,而是以base-2(二进制)存储。

基数为10的有限长度的数字可能是基数为2的重复小数。而且由于浮点数是固定大小,所以重复小数点会被截断,导致不准确。

当您使用as_integer_ratio作为基数为2的重复小数的数字时,由于base-10到base-2转换中的轻微不准确,您会得到一个有点愚蠢的分数。如果您将这两个数字相除,则该值将非常接近您的原始数字。

例如,虽然基数为10的1/10 = 0.1并且不是重复的小数,但它实际上是基数为2的重复小数。就像1/3 = 0.333 ...以10为底。

>>> (0.1).as_integer_ratio() 
(3602879701896397, 36028797018963968) 

如果Python的产量为精确,你会看到这甚至当你在提示符下输入只是0.1,通过让像1.00000 ... 01作为输出。但Python 在一般情况下隐藏了这种不准确的结果,导致混淆。

+0

看起来像一个更准确的答案。这可能是这个问题的原因吗? '>>> 0.1 + 0.1 + 0.1-0.3' '5.551115123125783e-17' –

+0

@AbdulHaseeb:这不是真正的原因,原因就像我解释的那样,可以表示的数字不需要以基数表示, 10与基于2的可以不同。 –

2

这实际上是一个非常好的问题。不同结果背后的原因是x并非真正的1232.23,因为1232.23没有精确的浮点数表示,因此1232.23的最接近的浮点数表示的分数表示为2709702426188841/2199023255552,但是当您使用str(1232.23)时,它将其视为精确值1232.23并返回数字的真正最佳分数表示。