如何检查浮点数是否为整数

302

我正在尝试找到最大的立方根整数,它小于12000。

processing = True
n = 12000
while processing:
    n -= 1
    if n ** (1/3) == #checks to see if this has decimals or not

不过我不确定如何检查它是否为整数!我可以将其转换为字符串,然后使用索引来检查末尾的值并查看它们是否为零,但这似乎相当麻烦。有更简单的方法吗?


4
让n的立方小于12000会使得工作更加容易。具体来说,将n取为立方根时可以达到这个目标。(即 n --> (n * n * n < 12000)) - suspectus
顺便问一下,你是指最大的整数立方体吗?对于小值,可以通过向下舍入并使用 int(12000**(1/3))**3 进行计算。 - qwr
15个回答

563

要检查浮点数是否为整数,请使用float.is_integer()方法

>>> (1.0).is_integer()
True
>>> (1.555).is_integer()
False

该方法在Python 2.6中被添加到float类型中。
请注意,在Python 2中,1/3是0(整数操作数的地板除法!),浮点运算可能不精确(float使用二进制分数进行近似,而不是精确的实数)。但稍微调整一下循环,就可以得到以下结果:
>>> for n in range(12000, -1, -1):
...     if (n ** (1.0/3)).is_integer():
...         print n
... 
27
8
1
0

这意味着任何大于3的立方数(包括10648在内)都因上述不精确而被忽略了。
>>> (4**3) ** (1.0/3)
3.9999999999999996
>>> 10648 ** (1.0/3)
21.999999999999996

你需要检查接近整数的数字,或者不使用float()来找到你的数字。比如将12000的立方根向下取整:

>>> int(12000 ** (1.0/3))
22
>>> 22 ** 3
10648

如果您使用的是Python 3.5或更高版本,则可以使用math.isclose()函数来判断浮点数值是否在可配置的范围内:
>>> from math import isclose
>>> isclose((4**3) ** (1.0/3), 4)
True
>>> isclose(10648 ** (1.0/3), 22)
True

对于旧版本,该函数的朴素实现(跳过错误检查并忽略无穷大和NaN),如在PEP485中提到

def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

不懂Python的话,这种说法会让我感到紧张,因为它似乎需要完美的数学才能在现实世界中发挥作用。 - Peter M
1
@PeterM:如果没有小数,该方法确实只返回“True”。当然,OP可能对浮点运算和精度有误解。 - Martijn Pieters
1
@MartijnPieters 没错,浮点数计算中只要一个小错误,你就会突然出现这些不需要的小数位,比如0.00000000000000000001。 - Peter M
1
@PeterM:在Python 2中,默认表示法将四舍五入为16位数字;“1.0000000000000001”显示为“1.0”,在Python 3中,显示产生相同值的最短字符串表示。 - Martijn Pieters
确实,但是拥有两种等效的方法来测试一个值(int或float)是否为整数仍然是很好的。而不是使用isinstance(x, int) or x.is_integer()float(x).is_integer()。但没关系,我可以接受这些解决方案! - Bill
显示剩余5条评论

70
我们可以使用取模(%)运算符。它告诉我们在将x除以y时有多少余数,表示为x % y。每个整数必须被1整除,所以如果有余数,它就不是一个整数。
这个函数将返回一个布尔值TrueFalse,取决于n是否为整数。
def is_whole(n):
    return n % 1 == 0

这是更好的答案,因为它也适用于n恰好是整数的情况。而被接受的答案在这种情况下会失败。 - emilaz

20

你可以使用这个:

if k == int(k):
    print(str(k) + " is a whole number!")

7
当数字变得更大时,它就会失败,而.is_integer()仍然可以工作。 - jfs
在我看来,你的链接并没有显示它不起作用。它只是表明大浮点数会失去精度。is_integer使用了类似的方法(o = (floor(x) == x) ? Py_True : Py_False;)。但我同意,应该使用is_integer(),因为它更清晰易懂。 - Juri Robl
2
是的。这只是表明大浮点数可能会失去精度,即使 large_float == float(large_int) 也可能失败。 - jfs
2
"123456789012345678901234567890.0 != 123456789012345678901234567890" 但是 "123456789012345678901234567890.0 == float(123456789012345678901234567890)" - jfs
3
是的,但是如果 k = 123456789012345678901234567890.0,则 k == int(k) 的结果为 True,这是正确的答案。 - Juri Robl
显示剩余2条评论

13

你不需要循环或检查任何内容。只需取12000的立方根并将其向下舍入:

r = int(12000**(1/3.0))
print r*r*r # 10648

9
你可以使用 模数 运算来实现。
if (n ** (1.0/3)) % 1 != 0:
    print("We have a decimal number here!")

2
如果 n 是 6.2、6.0、6.12312412 中的任意一个,我们都会得到 "We have a decimal number here!" 吗? - Jay Wang
@JayWong 不确定你是如何加载你的测试数据的,但是在我的机器上使用Python3.7可以正常工作。 - Zchpyvr

7
怎么样?
if x%1==0:
    print "is integer"

6

测试立方根不是更容易吗?从20(20**3 = 8000)开始,一直到30(30**3 = 27000)。然后您只需要测试少于10个整数。

for i in range(20, 30):
    print("Trying {0}".format(i))
    if i ** 3 > 12000:
        print("Maximum integral cube root less than 12000: {0}".format(i - 1))
        break

1
此外,浮点数存在舍入误差,因此在计算 n**(1/3) 是否为整数时可能会错过数字。例如,在我的计算机上,10648**(1/3)=21.999999999999996 而不是 22:有问题!使用这个答案的方法就没有这样的问题。我认为这是从数学角度来看唯一正确的解决方案(其他解决方案在 Python 中是正确的)。 - JPG

5
上述答案适用于许多情况,但它们却忽略了一些情况。考虑以下内容:
fl = sum([0.1]*10)  # this is 0.9999999999999999, but we want to say it IS an int

使用这个作为基准,其他一些建议并不能得到我们想要的行为:
fl.is_integer() # False

fl % 1 == 0     # False

相反尝试:

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

def is_integer(fl):
    return isclose(fl, round(fl))

现在我们得到:

is_integer(fl)   # True

isclosePython 3.5+ 中的函数,对于其他版本的 Python,您可以使用与相应 PEP 中提到的大致等效的定义。


1
math.fsum([0.1] * 10) == 1 - Asclepius

3

顺便提一下,is_integer 内部实际上是这样做的:

import math
isInteger = (math.floor(x) == x)

并不是完全用Python实现,但cpython的实现与上述提到的类似。

2
您可以使用类似以下的代码:

您可以使用类似以下的代码:

num = 1.9899
bool(int(num)-num)
#returns True

如果它为True,这意味着它具有一些值,因此不是整数。否则
num = 1.0
bool(int(num)-num)
# returns False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接