我想区分一些数字,例如
2.0
或2
以及诸如2.4
之类的实际小数。最好的方法是什么?目前我正在做:
def is_fractional(num):
if not str(num).replace('.','').isdigit(): return
return float(num) != int(num)
>>> is_fractional(2)
False
>>> is_fractional(2.1)
True
>>> is_fractional(2.0)
False
>>> is_fractional('a')
>>>
答案 0 :(得分:7)
该操作是内置的:
>>> 5.0.is_integer()
True
>>> 5.00000001.is_integer()
False
>>> 4.9999999.is_integer()
False
文档为here。
添加
初始解决方案仅适用于float
。这是带有测试的更完整答案:
from decimal import Decimal
def is_integer(x):
if isinstance(x, int):
return True
elif isinstance(x, float):
return x.is_integer()
elif isinstance(x, Decimal):
return x.as_integer_ratio()[1] == 1
return False
good = [
0,
0.0,
3,
-9999999999999999999999,
-2.0000000000000,
Decimal("3.000000"),
Decimal("-9")
]
bad = [
-9.99999999999999,
"dogs",
Decimal("-4.00000000000000000000000000000000001"),
Decimal("0.99999999999999999999999999999999999")
]
for x in good:
assert is_integer(x)
for x in bad:
assert not is_integer(x)
print("All tests passed")
答案 1 :(得分:3)
如果您的某些数字是decimal.Decimal
,则取决于精度,它们可能存在范围问题,无法转换为浮点数或丢弃实际存在的小数部分:
>>> import decimal
>>> x = decimal.Decimal('1.00000000000000000000000000000000000001')
>>> str(x)
'1.00000000000000000000000000000000000001'
>>> float(x).is_integer()
True
>>> y = decimal.Decimal('1e5000')
>>> str(y)
'1E+5000'
>>> float(y)
inf
str
方法通常可以正常工作(如上面所示的模态问题案例),因此您可以坚持使用,但是尝试使用is_integer
并使用后备选项可能会更好失败:
try:
return x.is_integer()
except AttributeError:
pass
(如其他人所述,您也需要在此处检查int
和long
,如果它们是允许的类型,因为它们在定义上是整数,但缺少is_integer
属性)。
这时,值得考虑所有其他答案,但这是一个特定的十进制。十进制处理程序:
# optional: special case decimal.Decimal here
try:
as_tuple = x.as_tuple()
trailing0s = len(list(itertools.takewhile(lambda i: i == 0, reversed(as_tuple[1]))))
return as_tuple[2] + trailing0s < 0
except (AttributeError, IndexError): # no as_tuple, or not 3 elements long, etc
pass
答案 2 :(得分:2)
为什么不检查截断整数和精确值之间的差是否不为零?
is_frac = lambda x: int(x)-x != 0
答案 3 :(得分:1)
Python包含一个fractions
模块,该模块从字符串,float
,整数等等中产生分数(有理数)。只需创建一个Fraction
并检查其分母是否不是1(Fraction
构造函数会自动将数字减为最低的项):
from fractions import Fraction
def is_fractional(num):
return Fraction(num).denominator != 1
请注意,如果转换为小数部分失败,则上述方法可能会引发异常。在这种情况下,未知对象是否为分数。
答案 4 :(得分:0)
如果您正在处理decimal
模块或float
对象,则可以轻松地做到这一点:
def is_factional(num):
return isinstance(num, (float, Decimal))
答案 5 :(得分:0)
这是一种实现方法(假设2/2不是您认为的“分数”):
# could also extend to other numeric types numpy.float32
from decimal import Decimal
def is_frac(n):
numeric_types = (int, float, Decimal)
assert isinstance(n, numeric_types), 'n must be numeric :/'
# (ints are never fractions)
if type(n) is int: return False
return n != float(int(n))
# various sorts of numbers
ns = [-1, -1.0, 0, 0.1, 1, 1.0, 1., 2.3, 1e0, 1e3, 1.1e3,
Decimal(3), Decimal(3.0), Decimal(3.1)]
# confirm that values are as expected
dict(zip(ns, [is_frac(n) for n in ns]))
这仅在n
是int
或float
或decimal.Decimal
的情况下有效。但是您可以通过将其包括在numpy.float64
中来扩展它以处理其他数字类型,例如numpy.int32
或numeric_types
。