【问题标题】:Testing for positive infinity, or negative infinity, individually in Python在 Python 中单独测试正无穷大或负无穷大
【发布时间】:2015-03-22 01:02:28
【问题描述】:

math.isinf() 测试合并在一起的正无穷或负无穷。什么是 pythonic 的方式来明确地测试它们?

测试正无穷大的方法:

  1. x == float('+inf')
  2. math.isinf(x) and x > 0

测试负无穷大的方法:

  1. x == float('-inf')
  2. math.isinf(x) and x < 0

拆卸方式一:

>>> def ispinf1(x): return x == float("inf")
...
>>> dis.dis(ispinf1)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_GLOBAL              0 (float)
              6 LOAD_CONST               1 ('inf')
              9 CALL_FUNCTION            1
             12 COMPARE_OP               2 (==)
             15 RETURN_VALUE

拆卸方式二:

>>> def ispinf2(x): return isinf(x) and x > 0
...
>>> dis.dis(ispinfs)
  1           0 LOAD_GLOBAL              0 (isinf)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 JUMP_IF_FALSE_OR_POP    21
             12 LOAD_FAST                0 (x)
             15 LOAD_CONST               1 (0)
             18 COMPARE_OP               4 (>)
        >>   21 RETURN_VALUE

This answer 似乎更喜欢方式 2,除了 x>0。

【问题讨论】:

    标签: python infinity


    【解决方案1】:

    “pythonic”的方式是采用可读和可维护的方式。

    也就是说,x == float("inf")x == float("-inf") 对我来说更具可读性,我更喜欢它们。 math.isinf(x) and x > 0 更快,但每次调用只需要大约 40 纳秒

    因此,除非您检查大量数字,否则运行时间不会有太大差异。

    【讨论】:

    • 如果你也在使用,例如,sympy,math.isinf(sympy.oo) 将给出正确答案,而 sympy.oo == float("inf") 将是错误的。
    • 还可以将float("inf")float("-inf") 的结果存储在变量中,以避免上面提到的小惩罚。
    • “每次调用只有 40 大约 40 纳秒”?只要???这是 CPU 时间的十年
    【解决方案2】:

    还有numpy

    >>> import numpy as np
    >>> np.isneginf([np.inf, 0, -np.inf])
    array([False, False,  True], dtype=bool)
    >>> np.isposinf([np.inf, 0, -np.inf])
    array([ True, False, False], dtype=bool)
    

    然后就是一般isinf

    >>> np.isinf([np.inf, 0, -np.inf])
    array([ True, False,  True], dtype=bool)
    

    【讨论】:

      【解决方案3】:

      这里有一些jupyterlab计时测试,看看什么是最快的方式(从最慢到最快排序):

      准备工作:

      import math
      import numpy as np
      n = 100000000
      a = list(range(n))
      a.extend([np.inf, float('inf'), math.inf])
      

      结果:

      %%time
      def inf_to_none(x):
          if np.isinf(x):
              return None
          else:
              return x
      r = list(map(inf_to_none, a))
      
      >> CPU times: user 1min 30s, sys: 481 ms, total: 1min 31s
      Wall time: 1min 31s
      
      
      %%time
      def inf_to_none(x):
          if x == float('inf'):
              return None
          else:
              return x
      r = list(map(inf_to_none, a))
      
      >> CPU times: user 19.6 s, sys: 494 ms, total: 20.1 s
      Wall time: 20.2 s
      
      
      %%time
      def inf_to_none(x):
          if math.isinf(x):
              return None
          else:
              return x
      r = list(map(inf_to_none_math, a))
      
      >> CPU times: user 15 s, sys: 292 ms, total: 15.3 s
      Wall time: 15.3 s
      
      
      %%time
      d = {np.inf: None}
      l = lambda x: d.get(x,x)
      r = list(map(l, a))
      
      >> CPU times: user 11.7 s, sys: 256 ms, total: 12 s
      Wall time: 12 s
      
      
      %%time
      def inf_to_none(x):
          if x == np.inf:
              return None
          else:
              return x
      r = list(map(inf_to_none, a))
      
      >> CPU times: user 11.2 s, sys: 280 ms, total: 11.5 s
      Wall time: 11.5 s
      
      
      %%time
      def inf_to_none(x):
          if x == math.inf:
              return None
          else:
              return x
      r = list(map(inf_to_none, a))
      
      >> CPU times: user 11 s, sys: 276 ms, total: 11.3 s
      Wall time: 11.3 s
      

      我认为这些结果很有趣,可以简短地使用== 进行比较。

      【讨论】:

      • 这在速度受到威胁的罕见情况下会很有趣。在这种情况下,全局变量会有所改善,例如from math import isinfpinf = float('+inf')
      猜你喜欢
      • 1970-01-01
      • 2013-11-29
      • 2017-08-19
      • 2022-08-12
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 2019-03-19
      • 1970-01-01
      相关资源
      最近更新 更多