除零等于零

oct*_*pus 29 python division zero

我怎么能忽视ZeroDivisionError并制造n / 0 == 0

dav*_*ism 56

在分割之前检查分母是否为零.这样可以避免捕获异常的开销,如果您希望将其除以很多,这可能会更有效.

def weird_division(n, d):
    return n / d if d else 0
Run Code Online (Sandbox Code Playgroud)


Cor*_*mer 25

你可以使用try/ exceptblock.

def foo(x,y):
    try:
        return x/y
    except ZeroDivisionError:
        return 0

>>> foo(5,0)
0

>>> foo(6,2)
3.0
Run Code Online (Sandbox Code Playgroud)


Ric*_*ica 15

我认为try except(正如在Cyber​​的回答中)通常是最好的方式(而且更多pythonic:更好地请求宽恕而不是请求许可!),但这是另一个:

def safe_div(x,y):
    if y == 0:
        return 0
    return x / y
Run Code Online (Sandbox Code Playgroud)

但是,赞成这样做的一个论点是,如果你期望ZeroDivisionErrors经常发生,提前检查0分母会快得多(这是python 3):

import time

def timing(func):
    def wrap(f):
        time1 = time.time()
        ret = func(f)
        time2 = time.time()
        print('%s function took %0.3f ms' % (f.__name__, int((time2-time1)*1000.0)))
        return ret
    return wrap

def safe_div(x,y):
    if y==0: return 0
    return x/y

def try_div(x,y):
    try: return x/y
    except ZeroDivisionError: return 0

@timing
def test_many_errors(f):
    print("Results for lots of caught errors:")
    for i in range(1000000):
        f(i,0)

@timing
def test_few_errors(f):
    print("Results for no caught errors:")
    for i in range(1000000):
        f(i,1)

test_many_errors(safe_div)
test_many_errors(try_div)
test_few_errors(safe_div)
test_few_errors(try_div)
Run Code Online (Sandbox Code Playgroud)

输出:

Results for lots of caught errors:
safe_div function took 185.000 ms
Results for lots of caught errors:
try_div function took 727.000 ms
Results for no caught errors:
safe_div function took 223.000 ms
Results for no caught errors:
try_div function took 205.000 ms
Run Code Online (Sandbox Code Playgroud)

因此,try except对于许多(或实际上,所有)错误,使用速度要慢3到4倍; 也就是说:对于捕获错误的迭代,它会慢3到4倍.if当有少量(或实际上没有)错误时,使用该语句的版本会稍微变慢(10%左右).

  • 当你最常使用`except`子句时,`try except`会慢一些.在这种情况下,总是.如果你知道只有1000次中的1次,你得到除以0,"尝试除了"会更快.因此,您的测试仅与最小的案例子集相关. (3认同)

twa*_*lig 7

def foo(x, y):
    return 0 if y == 0 else x / y
Run Code Online (Sandbox Code Playgroud)

  • 我只是好奇。为什么其他答案比这个答案获得更多票数?我理解Cyber​​越来越多,但其他2个也与此相同。 (2认同)

ToT*_*ire 5

解决方案

当您想要高效处理ZeroDivisionError(除以零)时,您不应该使用异常或条件。

result = b and a / b or 0  # a / b
Run Code Online (Sandbox Code Playgroud)

它是如何运作的?

  • b != 0我们有True and a / b or 0. True and a / b等于a / ba / b or 0等于a / b
  • b == 0我们有False and a / b or 0. False and a / b等于FalseFalse or 0等于0

基准

Timer unit: 1e-06 s

Total time: 118.362 s
File: benchmark.py
Function: exception_div at line 3

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     3                                           @profile
     4                                           def exception_div(a, b):
     5 100000000   23419098.5      0.2     19.8      try:
     6 100000000   40715642.9      0.4     34.4          return a / b
     7 100000000   28910860.8      0.3     24.4      except ZeroDivisionError:
     8 100000000   25316209.7      0.3     21.4          return 0

Total time: 23.638 s
File: benchmark.py
Function: conditional_div at line 10

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    10                                           @profile
    11                                           def conditional_div(a, b):
    12 100000000   23638033.3      0.2    100.0      return a / b if b else 0

Total time: 23.2162 s
File: benchmark.py
Function: logic_div at line 14

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    14                                           @profile
    15                                           def logic_div(a, b):
    16 100000000   23216226.0      0.2    100.0      return b and a / b or 0
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是一个非常棒的答案。它应该是最受好评的一个,感谢分享这个漂亮的技巧! (4认同)