对于给定的 fp 精度,检查 Python 中的数字是否有理数
我想知道在 python 中检查数字 x 是否是有理数(存在两个整数 n,m 使得 x=n/m)的好方法。
在 Mathematica 中,这是通过函数 Rationalize[6.75]
完成的:27/4
我假设这个问题有给定精度的答案。 是否有获取这两个整数的通用算法?
I would like to know a good way of checking if a number x is a rational (two integers n,m exist so that x=n/m) in python.
In Mathematica, this is done by the function Rationalize[6.75]
: 27/4
I assume this question has an answer for a given accuracy.
Is there a common algorithm of obtaining these two integers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
在 python >= 2.6 中,浮点上有一个
as_integer_ratio
方法:但是,由于编程语言中定义浮点数的方式,不存在无理数。
In python >= 2.6 there is a
as_integer_ratio
method on floats:However, due to the way floats are defined in programming languages there are no irrational numbers.
浮点数的本质意味着检查浮点数是否有理数是没有意义的,因为所有浮点数实际上都是 n 形式的分数> / 2e。但是,您可能很想知道是否存在一个非常接近给定浮点数的简单分数(分母较小,而不是 2 的大幂)。
Donald Knuth 在《计算机编程艺术》第二卷中讨论了后一个问题。请参阅练习 4.53-39 的答案。这个想法是通过将范围的端点扩展为连分数来搜索一个范围内分母最小的分数,只要它们的系数相等,然后当它们不同时,取它们之间最简单的值。这是 Python 中相当简单的实现:
以下是一些结果:
The nature of floating-point numbers means that it makes no sense to check if a floating-point number is rational, since all floating-point numbers are really fractions of the form n / 2e. However, you might well want to know whether there is a simple fraction (one with a small denominator rather than a big power of 2) that closely approximates a given floating-point number.
Donald Knuth discusses this latter problem in The Art of Computer Programming volume II. See the answer to exercise 4.53-39. The idea is to search for the fraction with the lowest denominator within a range, by expanding the endpoints of the range as continued fractions so long as their coefficients are equal, and then when they differ, take the simplest value between them. Here's a fairly straightforward implementation in Python:
And here are some results:
任何具有有限小数展开式的数都是有理数。例如,您总是可以
通过说它对应于
So 来解决,因为浮点数和双精度数具有有限精度,它们都是有理数。
Any number with a finite decimal expansion is a rational number. You could always solve for instance
by saying that it corresponds to
So since floats and doubles have finite precision they're all rationals.
Python 使用浮点表示而不是有理数。查看标准库
fractions
模块了解一些详细信息关于有理数。例如,观察这个,看看为什么会出错:(
哦,你想看看它有效的案例吗?)
Python uses floating-point representation rather than rational numbers. Take a look at the standard library
fractions
module for some details about rational numbers.Observe, for example, this, to see why it goes wrong:
(Oh, you want to see a case where it works?)
您可能会对此感兴趣:最佳有理近似
May be this will be interesting to you: Best rational approximation
正如您所指出的,任何浮点数都可以通过移动小数点并除以适当的十次方来转换为有理数。
然后,您可以从被除数和除数中删除最大公约数,并检查这两个数字是否符合您选择的数据类型。
As you noted any floating point number can be converted to a rational number by moving the decimal point and dividing by the appropriate power of ten.
You can then remove the greatest common divisor from the dividend and divisor and check if both of these numbers fit in the data type of your choice.
编程语言中实数的问题在于,它们通常被定义为返回给定精度的有限表示的函数(例如,以 n 作为参数并返回 2^-n 精度内的浮点数的函数)。
您绝对可以将有理数/整数转换为实数,但即使比较实数是否相等也是不可判定的(这本质上是停止问题)。
你无法判断一个实数 x 是否是有理数:即使在数学中,这通常也很困难,因为你必须找到 p 和 q 使得 x = p/q,而这通常是非建设性的。
然而,给定一个精度窗口,您可以使用连续分数展开等方法找到该精度的“最佳”有理近似值。我相信这本质上就是mathematica 所做的事情。但在你的例子中,6.75 已经是有理数了。尝试用 Pi 代替。
The problem with real numbers in programming languages is that they are usually defined as functions returning a finite representation given an accuracy (eg. a function which takes n as an argument and returns a floating point number within 2^-n accuracy).
You can definitely turn a rational/integer into a real, but even comparing reals for equality is undecidable (it is essentially the halting problem).
You cannot tell whether a real number x is rational: even in mathematics, it is usually difficult, since you have to find p and q such that x = p/q, and this is often non constructive.
However, given an accuracy window, you can find the "best" rational approximation for this accuracy using for instance continuous fraction expansion. I believe that is essentially what mathematica does. But in your exemple, 6.75 is already rational. Try with Pi instead.