float.as_integer_ratio()的实现限制

tra*_*god 11 python math

最近,一位记者提到float.as_integer_ratio()了Python 2.6中的新内容,指出典型的浮点实现基本上是实数的有理近似.好奇,我不得不尝试π:

>>> float.as_integer_ratio(math.pi);
(884279719003555L, 281474976710656L)
Run Code Online (Sandbox Code Playgroud)

由于Arima,我没有看到更准确的结果,我感到有点惊讶,:

(428224593349304L, 136308121570117L)
Run Code Online (Sandbox Code Playgroud)

例如,这段代码:

#! /usr/bin/env python
from decimal import *
getcontext().prec = 36
print "python: ",Decimal(884279719003555) / Decimal(281474976710656)
print "Arima:  ",Decimal(428224593349304) / Decimal(136308121570117)
print "Wiki:    3.14159265358979323846264338327950288"
Run Code Online (Sandbox Code Playgroud)

产生这个输出:

python:  3.14159265358979311599796346854418516
Arima:   3.14159265358979323846264338327569743
Wiki:    3.14159265358979323846264338327950288

当然,考虑到64位浮点数提供的精度,结果是正确的,但它让我问:我怎样才能找到更多有关实现限制的结果 as_integer_ratio()?谢谢你的指导.

其他链接:Stern-Brocot树Python源代码.

Ale*_*lli 5

我可以推荐Stern-Brocot 树gmpy的实现吗:

>>> import gmpy
>>> import math
>>> gmpy.mpq(math.pi)
mpq(245850922,78256779)
>>> x=_
>>> float(x)
3.1415926535897931
>>> 
Run Code Online (Sandbox Code Playgroud)

同样,结果是“在 64 位浮点精度内正确”(53 位“所谓的”尾数;-),但是:

>>> 245850922 + 78256779
324107701
>>> 884279719003555 + 281474976710656
1165754695714211L
>>> 428224593349304L + 136308121570117
564532714919421L
Run Code Online (Sandbox Code Playgroud)

...gmpy 的精度比 Arima 的精度便宜得多(就分子和分母值的总和而言),更不用说 Python 2.6 的精度了!-)


小智 5

使用以下方法可获得更好的近似值

fractions.Fraction.from_float(math.pi).limit_denominator()
Run Code Online (Sandbox Code Playgroud)

由于可能是3.0版,因此包含小数部分。但是,math.pi的精度不足以返回30位数的近似值。


Vic*_*Liu 3

所使用的算法as_integer_ratio考虑分母中的 2 次幂。这是一个(可能)更好的算法

  • 说算法不准确是一个有缺陷的解释。`float.as_integer_ratio()` 只是返回一个(分子,分母)对,它“严格等于”所讨论的浮点数(这就是为什么分母是 2 的幂,因为标准浮点数有一个以 2 为底的指数)。精度的损失来自浮点表示本身,*不是*来自 float.as_integer_ratio() ,它实际上是无损的。 (15认同)