【问题标题】:Python: return float 1.0 as int 1 but float 1.5 as float 1.5 [duplicate]Python:将float 1.0返回为int 1,但将float 1.5返回为float 1.5 [重复]
【发布时间】:2019-08-25 21:18:01
【问题描述】:

在 Python 中有没有办法将 1.0 转换为整数 1 而同一函数忽略 1.5 并将其保留为 float

现在,int() 将把1.0 变成1,但它也会将1.5 舍入到1,这不是我想要的。

【问题讨论】:

  • 一种方法是使用is_integer() 检查浮点数,如果通过,将其转换为int?
  • 浮点数是近似值,1.0 实际上可能是 1.000000000000010.999999999999
  • 请注意,由于duck typing,您想要实现的这段文字可能不合适或无用,具体取决于上下文。
  • 请用文字/规则来说明您的确切要求,而不仅仅是一个例子!
  • def f(x): if x == 1.0: return 1 else return 1.5

标签: python floating-point integer


【解决方案1】:

从上面的 cmets 继续:

使用is_integer():

来自docs的示例

>>> (1.5).is_integer()
False
>>> (1.0).is_integer()
True
>>> (1.4142135623730951).is_integer()
False
>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False

输入

s = [1.5, 1.0, 2.5, 3.54, 1.0, 4.4, 2.0]

因此

print([int(x) if x.is_integer() else x for x in s])

封装在一个函数中:

def func(s):
    return [int(x) if x.is_integer() else x for x in s]

print(func(s))

如果你不想要任何import

def func(s):
    return [int(x) if x == int(x) else x for x in s]

print(func(s))

map()lambda 函数和迭代器s 一起使用:

print(list(map(lambda x: int(x) if x.is_integer() else x, s)))

print(list(map(lambda x: int(x) if int(x) == x else x, s)))

输出

[1.5, 1, 2.5, 3.54, 1, 4.4, 2]

【讨论】:

  • 如果有人对 is_integer() 的限制以及浮点数与 1.0 的距离可以并且仍然被视为整数感到好奇,我编写了一个简短的脚本来找到限制。这是一个非常小的数字,比我以往任何时候都需要的精度要高得多。 (1.0 + 1.1102230246251566636831481088739149080825883254353483864385054857848444953560829162597656251e-16).is_integer()返回假,但是(1.0 + 1.1102230246251566636831481088739149080825883254353483864385054857848444953560829162597656250e-16).is_integer()返回真。跨度>
  • @JoshDavis 这只是舍入到 1.01.0 + sys.float_info.epsilon
  • 我在这里看到的所有基于is_integer 的解决方案,如果它们收到一个整数值,都会惨遭失败,因为整数没有那种方法。为了安全起见,这样的事情会有所帮助:to_int = lambda x: int(x) if float(x).is_integer() else x
  • @accdias:这也不总是有效,因为float 有代表性限制,而int 没有。传递x = 1 << 1024 将导致您的代码以OverflowError 终止。因此,现在您对安全性或异常处理进行了额外检查。
  • @ShadowRanger,这是真的,但我很确定大多数人永远不会达到1 << 1024 的限制,如果有的话。另一方面,我认为看到有人尝试做2 .is_integer()float(1<<1024) 更可行。无论如何都是好信息。
【解决方案2】:

float.is_integer 是浮点数上的一个方法,它返回浮点数是否表示整数。

你可以使用我创建的这个名为to_int的函数,它使用is_integer来检查它是否代表一个整数(例如1.0)或不是(例如1.5)。

如果是整数,返回int(a),否则返回原值。

如你所见,我没有使用elifelse,因为return 只返回一次:

def to_int(a):
   if a.is_integer():
      return int(a)
   return a

print(to_int(1.5))
print(to_int(1.0))

输出:

1.5
1

【讨论】:

    【解决方案3】:

    我过去在 C++ 中所做的是,假设你有这些变量:

    float x = 1.5;
    float y = 1.0;
    

    然后你可以这样做:

    if(x == (int)x) 
        return 1;
    else return 0;
    

    这将返回 0,因为 1.5 不等于 1

    if(y == (int)y) 
        return 1;
    else return 0;
    

    这将返回 1,因为 1.0 等于 1

    当然你的问题是关于 Python 的,is_integer() 函数应该很好用,我只是觉得有些人可能会觉得这很有用。

    【讨论】:

    • 问题是只要有问题的浮点数具有整数值,就将浮点数转换为 int。 AFAIK 这在 C++ 中是不可能的,因为你不能从函数返回不同的值。
    • @M.Herzkamp 你可以有一个union
    • 如果满足上述条件,您还可以设置另一个整数变量并将浮点数保存在那里
    • 关于 C++ 的题外话并不真正相关。你可以在 Python 中做同样的事情:foo = lambda x: int(x) if int(x) == x else x。 (或者在 Python 3.8 中,避免重复调用 intlambda x: y if (y:=int(x)) == x else x
    • filter 不会修改列表中的值;该函数只是一个谓词,它决定是否选择其输出的原始值。请改用map
    【解决方案4】:

    您可以做的一个简单的事情是使用模运算符:

    if (myFloat % 1 == 0) // Number is an int
    else // numer is not an int
    

    编辑:Python 代码

    if myFloat % 1 == 0:
      # myFloat is an integer.
    else:
      # myFloat is NOT an integer
    

    【讨论】:

      【解决方案5】:

      如果您的目标是将数字转换为简洁的字符串,您可以简单地将'%g'(“通用格式”)用于formatting

      >>> '%g' % 1.0
      '1'
      >>> '%g' % 1
      '1'
      >>> '%g' % 1.5
      '1.5'
      >>> '%g' % 0.3
      '0.3'
      >>> '%g' % 0.9999999999
      '1'
      

      您可以指定所需的精度:

      >>> '%.15g' % 0.999999999999999
      '0.999999999999999'
      >>> '%.2g' % 0.999
      '1'
      

      【讨论】:

      • 这很好,但我昨天有一个疑问,由于某种原因我不能问,这会将0.9 变成1 但考虑到一个人只想要1.012.02 而不是 0.911.92。在那种情况下我们有解决办法吗?干杯!
      • @DirtyBit:对不起,我真的不明白这个问题。 '%g' % 0.9'0.9''%g' % 2.0'2'。浮点数仅在非常接近 int 时才显示为 int,例如0.9999995。但不是0.90.99
      • 完全正确:print('%g' % 0.9999999999) # 1 但让我们说 req.如果是1.0 而不是0.9999999999,是否只有1
      • @DirtyBit:您可以指定所需的精度:'%.15g' % 0.999999999999999'0.999999999999999''%.2g' % 0.999is '1'。来自article舍入误差是浮点计算的特征
      • 最佳答案,因为这是 OP 想要的唯一有效用例。
      【解决方案6】:

      Python 浮点数是近似值,因此 打印1.0 的东西不一定完全是 1.0。如果您想查看某事物是否近似为整数,请使用足够小的 epsilon 值。

      EPSILON = 0.0001 # Make this smaller or larger depending on desired accuracy
      
      def func(x):
        if abs(x - round(x)) < EPSILON:
          return round(x)
        else:
          return x
      

      一般来说,如果您要检查某个浮点数是否为 ==,这往往是代码异味,因为浮点值本质上是近似值。一般来说,检查浮点数是否在某个 epsilon 范围内的某物附近更合适。

      【讨论】:

      • 虽然大多数浮点值都是近似值,但仍有许多整数可以精确表示。一个 64 位 IEEE 754 浮点数(用于 Python 和其他语言)可以准确地表示任何适合 53 位或更少的有符号整数。假设整数值可以用低至 53 位表示,则此类整数可以在 64 位浮点数和 64 位整数之间进行 1 到 1 的转换。根据 IEEE 754 规范,保持在 53 位整数空间内的加法、减法和乘法应该产生相同的结果。
      • @penguin359 虽然我同意整数可以用浮点数精确表示,但如果你处于 OP 所处的情况,你需要问自己有多接近一个整数对于您的目的来说“足够接近”。 1.0 + 1e-16“足够接近”吗?是1.0 + 2e-16?这是一个重要的问题,因为基于 IEEE 754 的“是整数”方法会以不同的方式对待它们,您可能想也可能不想考虑 1.0 + 2e-16“不是整数”而说 1.0 + 1e-16 是一个。 -- 有一个显式的 epsilon(相对于 IEEE 754 中的隐式 epsilon)让你的愿望更清晰。
      • 在这个答案中似乎最好的评论:设置一个 epsilon 就像在提供的示例中一样工作正常。或者,特别是在处理美分(一般的货币)时,我发现将 Python 的默认二进制表示更改为十进制表示更有用,由模块 decimal (docs.python.org/3.7/library/decimal.html) 提供。差异,例如在以 0.1 为增量从 -1 迭代到 +1 的循环中,要么非常接近 0,要么正好在 0.0 - 不需要 epsilon 集(你将如何处理 -1.3877787807814457e-16货币单位?)。
      • "所以打印为 1.0 的东西不一定是 1.0" 这取决于 python 的版本。在现代 python3(自 python 3.2 以来的 IIRC)中,打印为 1.0 的浮点数正好是 1.0。在旧版本的 python 中可能不是。试试“print (float(numpy.nextafter(1.0,2)))”看看你的版本会发生什么。
      【解决方案7】:

      对于数字列表:

      def get_int_if_possible(list_of_numbers):
          return [int(x) if x == int(x) else x for x in list_of_numbers]
      

      对于一个数字:

      def get_int_if_possible(number):
          return int(number) if number == int(number) else number
      

      【讨论】:

        【解决方案8】:
        def your_function(i):
          if i.is_integer():
            return int(i)
          else:
            return float(i)
        

        【讨论】:

        • 虽然这可能会回答问题,但如果您可以添加其中发生的事情以及它如何解决问题,这将非常有帮助,以延长您的答案的生命周期并吸引寻找类似解决方案的用户。
        • 字符串和浮点数有一个名为 is_integer 的函数,如果它是数字则返回 true,否则返回 false(包括浮点数)。因此,如果它是 int,则将其作为 int 返回。其他任何东西(它是一个浮点数)并将其作为浮点数返回。
        • @xcrafter_40 不是评论,您可以编辑您的答案以添加解释。 :)
        • 另一个反对票是什么?
        【解决方案9】:

        divmod 替代:

        def f(x):
            return x if divmod(x, 1)[1] else int(x)
        

        【讨论】:

          猜你喜欢
          • 2020-10-22
          • 1970-01-01
          • 1970-01-01
          • 2011-12-17
          • 1970-01-01
          • 2017-12-08
          • 1970-01-01
          • 1970-01-01
          • 2021-03-02
          相关资源
          最近更新 更多