对于给定的fp准确度,检查Python中的数字是否合理

Mer*_*moz 8 python algorithm math floating-point floating-accuracy

我想知道在python中检查数字x是否合理(两个整数n,m存在使得x = n/m)的好方法.

在Mathematica中,这是由函数完成的Rationalize[6.75]:27/4

我认为这个问题对于给定的准确性有一个答案.是否有获得这两个整数的通用算法?

Sil*_*ost 13

在python> = 2.6中as_integer_ratio,浮点数有一个方法:

>>> a = 6.75
>>> a.as_integer_ratio()
(27, 4)
>>> import math
>>> math.pi.as_integer_ratio()
(884279719003555, 281474976710656)
Run Code Online (Sandbox Code Playgroud)

然而,由于道路花车在编程语言定义,没有无理数.


Gar*_*ees 8

浮点数的性质意味着检查浮点数是否合理是没有意义的,因为所有浮点数实际上都是n/2 e形式的一部分.但是,您可能想知道是否存在一个与给定浮点数非常接近的简单分数(一个小分母而不是2的大幂).

Donald Knuth在"计算机程序设计艺术"第二卷中讨论了后一个问题.请参阅练习4.53-39的答案.这个想法是通过将范围的端点扩展为连续分数(只要它们的系数相等)来搜索范围内具有最小分母的分数,然后当它们不同时,在它们之间取最简单的值.这是Python中相当简单的实现:

from fractions import Fraction
from math import modf

def simplest_fraction_in_interval(x, y):
    """Return the fraction with the lowest denominator in [x,y]."""
    if x == y:
        # The algorithm will not terminate if x and y are equal.
        raise ValueError("Equal arguments.")
    elif x < 0 and y < 0:
        # Handle negative arguments by solving positive case and negating.
        return -simplest_fraction_in_interval(-y, -x)
    elif x <= 0 or y <= 0:
        # One argument is 0, or arguments are on opposite sides of 0, so
        # the simplest fraction in interval is 0 exactly.
        return Fraction(0)
    else:
        # Remainder and Coefficient of continued fractions for x and y.
        xr, xc = modf(1/x);
        yr, yc = modf(1/y);
        if xc < yc:
            return Fraction(1, int(xc) + 1)
        elif yc < xc:
            return Fraction(1, int(yc) + 1)
        else:
            return 1 / (int(xc) + simplest_fraction_in_interval(xr, yr))

def approximate_fraction(x, e):
    """Return the fraction with the lowest denominator that differs
    from x by no more than e."""
    return simplest_fraction_in_interval(x - e, x + e)
Run Code Online (Sandbox Code Playgroud)

以下是一些结果:

>>> approximate_fraction(6.75, 0.01)
Fraction(27, 4)
>>> approximate_fraction(math.pi, 0.00001)
Fraction(355, 113)
>>> approximate_fraction((1 + math.sqrt(5)) / 2, 0.00001)
Fraction(377, 233)
Run Code Online (Sandbox Code Playgroud)


aio*_*obe 5

具有有限十进制扩展的任何数字都是有理数.你总是可以解决这个问题

5.195181354985216
Run Code Online (Sandbox Code Playgroud)

通过说它对应于

5195181354985216 / 1000000000000000
Run Code Online (Sandbox Code Playgroud)

因此,因为浮点数和双精度具有有限的精度,所以它们都是有理数的.


Chr*_*gan 5

Python 使用浮点表示而不是有理数。查看标准库fractions模块以获取有关有理数的一些详细信息。

例如,观察这个,看看为什么会出错:

>>> from fractions import Fraction
>>> 1.1  # Uh oh.
1.1000000000000001
>>> Fraction(1.1)  # Will only work in >= Python 2.7, anyway.
Fraction(2476979795053773, 2251799813685248)
>>> Fraction(*1.1.as_integer_ratio())  # Python 2.6 compatible
Fraction(2476979795053773, 2251799813685248)
Run Code Online (Sandbox Code Playgroud)

(哦,你想看看它有效的案例吗?)

>>> Fraction('1.1')
Fraction(11, 10)
Run Code Online (Sandbox Code Playgroud)

  • @SilentGhost:ABC 确实如此。查看 Guido 的经验以及为什么 Python 不这样做:http://python-history.blogspot.com/2009/03/problem-with-integer-division.html (2认同)