在Python中检查浮点数是否等于整数值
在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 个回答
你们的实现都有问题。实际上,可能会出现像 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
在Python的浮点数类型中,有一个叫做 is_integer
的函数:
>>> float(1.0).is_integer()
True
>>> float(1.001).is_integer()
False
>>>
你应该选择后者。在《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的指正,如果我让任何人走上错误的道路,我深表歉意。