在Python中检查浮点数是否等于整数值

27 投票
12 回答
30682 浏览
提问于 2025-04-16 18:48

在Python 3中,我想检查一个给定的值是否是三角形数,也就是说,它是否可以表示为 n * (n + 1) / 2,其中 n 是某个正整数。

我可以直接写:

import math

def is_triangular1(x):
    num = (1 / 2) * (math.sqrt(8 * x + 1) - 1)
    return int(num) == num

还是说我需要在一个容差范围内进行检查呢?

epsilon = 0.000000000001
def is_triangular2(x):
    num = (1 / 2) * (math.sqrt(8 * x + 1) - 1)
    return abs(int(num) - num) < epsilon

我检查过这两个函数在 x 的值达到1,000,000时返回的结果是一样的。但我不确定一般来说 int(x) == x 是否总能正确判断一个数字是否是整数,因为有些情况下,比如5可能会被表示为4.99999999999997等等。

据我所知,如果我在C语言中这样做,第二种方法是正确的,但我对Python 3不太确定。

12 个回答

11

你们的实现都有问题。实际上,可能会出现像 4.999999999999997 这样的结果,所以用 int() 是不行的。

我建议换个思路:首先假设你的数字是一个三角形数,然后计算一下在这种情况下 n 应该是多少。在这第一步中,你可以宽松地进行四舍五入,因为只有当这个数字确实是三角形数时,结果才需要准确。接下来,计算 n * (n + 1) / 2,然后把这个结果和 x 比较。现在,你比较的是两个整数,所以不会再有不准确的情况了。

计算 n 的过程可以通过展开来简化

(1/2) * (math.sqrt(8*x+1)-1) = math.sqrt(2 * x + 0.25) - 0.5

并利用

round(y - 0.5) = int(y)

对于正的 y 来说。

def is_triangular(x):
    n = int(math.sqrt(2 * x))
    return x == n * (n + 1) / 2
42

在Python的浮点数类型中,有一个叫做 is_integer 的函数:

>>> float(1.0).is_integer()
True
>>> float(1.001).is_integer()
False
>>> 
11

你应该选择后者。在《Programming in Python 3》这本书中,给出了一个例子,说明了比较浮点数的最准确方法。

def equal_float(a, b):
    #return abs(a - b) <= sys.float_info.epsilon
    return abs(a - b) <= chosen_value #see edit below for more info

另外,由于epsilon是“机器能区分两个浮点数之间的最小差异”,所以在你的函数中最好使用<=。

编辑:在阅读了下面的评论后,我回头看了一下书,书中明确提到“这是一个简单的函数,用于在机器精度的极限内比较浮点数是否相等”。我认为这只是一个用于极高精度比较浮点数的例子,但由于在很多浮点计算中会引入误差,所以这种方法应该很少使用,甚至根本不应该使用。我在我的回答中把它称为“最准确”的比较方式,从某种意义上来说是对的,但在比较浮点数或整数与浮点数时,这通常不是我们想要的。根据函数的“问题领域”选择一个值(例如:0.00000000001),而不是使用sys.float_info.epsilon,才是正确的方法。

感谢S.Lott和Sven Marnach的指正,如果我让任何人走上错误的道路,我深表歉意。

撰写回答