我已经看过许多问题,询问如何检查浮点数是否为整数。大多数答案似乎建议使用is_integer()
:
(1.0).is_integer()
(1.55).is_integer()
我偶尔也会看到math.floor()
被使用:
import math
1.0 == math.floor(1.0)
1.55 == math.floor(1.55)
我想知道为什么% 1
很少被使用或推荐?
1.0 % 1 == 0
1.55 % 1 == 0
为此目的使用modulo是否有问题?是否存在这种无法捕获的边缘情况?真正大数字的性能问题?
如果% 1
是一个很好的选择,那么我也想知道为什么is_integer()
被引入标准库?
似乎%
更灵活。例如,通常使用% 2
检查数字是奇数/偶数,还是使用% n
来检查某些内容是否是n
的倍数。鉴于这种灵活性,为什么要引入一个新方法(is_integer
)来做同样的事情,或者使用math.floor
,这两个方法都需要知道/记住它们存在并知道如何使用它们?我知道math.floor
除了整数检查之外还有其他用途,但仍然......
答案 0 :(得分:1)
一个明显的原因是:可读性
如果名为is_integer()
的函数返回True
,那么您所测试的内容就很明显了。
但是,使用模数解决方案时,必须仔细考虑该过程才能看到它实际上是在测试浮点数是否为整数。如果你将模数形式包装在一个具有明显名称的函数中,例如simon_says_its_an_integer()
,我认为它一样好(除了不必要地引入已有的函数)。
答案 1 :(得分:0)
所有这些都是有效的。 math.floor
选项要求特定值与floor函数的结果完全匹配。如果要将其封装在通用方法中,这不是很方便。所以它归结为第一个和第三个选项。两者都有效,并将完成这项工作。所以关键的区别很简单 - 性能:
from timeit import Timer
def with_isint(num):
return num.is_integer()
def with_mod(num):
return num % 1 == 0
Timer(lambda: with_isint(10.0)).timeit(number=10000000)
#output: 2.0617980659008026
Timer(lambda: with_mod(10.0)).timeit(number=10000000)
#output: 2.6560597440693527
当然,这是一个简单的操作,因此您需要进行大量调用才能看到相当大的差异,正如您在示例中所看到的那样。