检查float是否等于python中的整数值

时间:2011-06-01 23:49:17

标签: python floating-point

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

我可以写一下:

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。

11 个答案:

答案 0 :(得分:25)

python float类型中有is_integer函数:

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

答案 1 :(得分:10)

您的实施都存在问题。实际上可能会发生最终类似4.999999999999997的内容,因此使用int()不是一种选择。

我会采用一种完全不同的方法:首先假设你的数字是三角形,并计算n在这种情况下的情况。在第一步中,您可以慷慨地进行回合,因为如果实际的数字是三角形,则只需要得到正确的结果。接下来,为此n * (n + 1) / 2计算n,并将结果与​​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

答案 2 :(得分:8)

你会想做后者。在 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是“机器可以区分两个浮点数的最小差异”,因此您需要在函数中使用&lt; =。

编辑:在阅读了下面的评论之后,我回头看了一下这本书,它特别说明了“这是一个简单的函数,用于比较浮点数的相等性和机器精度的极限”。我相信这只是将浮点数与极端精度进行比较的一个例子,但事实上,许多浮点计算引入了错误,这种情况应该很少使用。我把它描述为在我的答案中比较的“最准确”的方式,在某种意义上它是正确的,但很少在将浮点数或整数与浮点数进行比较时的意图。根据函数的“问题域”而不是使用sys.float_info.epsilon选择值(例如:0.00000000001)是正确的方法。

感谢S.Lott和Sven Marnach的更正,如果我带领任何人走错路,我道歉。

答案 3 :(得分:5)

Python确实有一个Decimal类(在the decimal module中),您可以使用它来避免浮点数的不精确。

答案 4 :(得分:4)

浮点数可以精确地表示其范围内的所有整数 - 浮点相等只是在关注点之后的位时才是棘手的。因此,只要公式中的所有计算都返回您感兴趣的案例的整数,int(num)== num就完全安全了。

所以,我们需要证明,对于任何三角形数字,你所做的每一个数学运算都可以用整数运算来完成(任何以非整数形式出现的数据都必须意味着x不是三角形):

首先,我们可以假设x必须是一个整数 - 这在'三角数'的定义中是必需的。

在这种情况下,8 * x + 1也将是一个整数,因为整数在+和*下关闭。

math.sqrt()返回float;但如果x是三角形,则平方根将是一个整数 - 即,再次精确表示。

因此,对于应该在函数中返回true的所有x,int(num)== num将为true,因此istriangular1将始终有效。正如该问题的评论中所提到的,唯一的关键点是默认情况下Python 2以与C - int / int =&gt;相同的方式进行整数除法。 int,如果结果不能完全表示为int,则截断。所以,1/2 == 0.这在Python 3中得到修复,或者通过行

来修复
from __future__ import division

靠近代码顶部。

答案 5 :(得分:2)

我认为模块十进制是你需要的

答案 6 :(得分:1)

您可以将您的号码四舍五入到小数点后14位:

 >>> round(4.999999999999997, 14)
 5.0

PS:双精度约为15位小数

答案 7 :(得分:1)

很难与标准争论。

在C99和POSIX中,将float舍入为int的标准由nearbyint()定义。重要的概念是舍入方向和特定于语言环境的舍入约定。

假设约定是common rounding,这与Python中的C99约定相同:

#!/usr/bin/python

import math

infinity = math.ldexp(1.0, 1023) * 2

def nearbyint(x): 
   """returns the nearest int as the C99 standard would"""

   # handle NaN
   if x!=x:
       return x      

   if x >= infinity:
       return infinity

   if x <= -infinity:
       return -infinity

   if x==0.0:
       return x

   return math.floor(x + 0.5)

如果您想要更多地控制舍入,请考虑使用Decimal module并选择您希望使用的舍入约定。例如,您可能希望使用Banker's Rounding

确定约定后,舍入为int并与其他int进行比较。

答案 8 :(得分:1)

考虑使用NumPy,他们会照顾好一切。

import numpy as np

result_bool = np.isclose(float1, float2)

答案 9 :(得分:0)

Python仍然使用相同的浮点表示和C操作,所以第二个是正确的方法。

答案 10 :(得分:0)

在引擎盖下,Python的float类型是C double。

最强大的方法是将最接近的整数设置为num,然后测试整数是否满足您所追求的属性:

import math
def is_triangular1(x):
    num = (1/2) * (math.sqrt(8*x+1)-1 )
    inum = int(round(num))
    return inum*(inum+1) == 2*x  # This line uses only integer arithmetic