查看数字是否为小数的最佳方法

时间:2018-10-27 00:54:44

标签: python

我想区分一些数字,例如 2.02以及诸如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')
>>>

6 个答案:

答案 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

(如其他人所述,您也需要在此处检查intlong,如果它们是允许的类型,因为它们在定义上是整数,但缺少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]))

这仅在nintfloatdecimal.Decimal的情况下有效。但是您可以通过将其包括在numpy.float64中来扩展它以处理其他数字类型,例如numpy.int32numeric_types