如何在两个序列中散列值时处理被零除错误

时间:2011-05-10 00:59:04

标签: python mapping list-comprehension

我有两个固定长度的元组列表。此函数计算各个元素的分数(比率)(注意,fX()此处不会使用理解来提高可读性。)

>>> def fX(a,b):  
>>>    c=[]  
>>>    for i in range(len(a)):  
>>>        c.append([a[i][x]/float(a[i][x]+b[i][x]) for x in range(len(a[i]))])
>>>    return c  

当所有值都不为零时,fX()有效:

>>> a[0]=(3, 4, 17, 9.6667, 6.6583, 0.4310, 1)  
>>> b[0]=(4, 4, 12, 8.0, 3.2660, 0.0002, 1)  
>>> fX(a,b)  
>>> [[0.4286, 0.5, 0.5862, 0.5472, 0.6710, 0.9995, 0.5]]  

但是,当任何一对的值总和为零时,fX()会失败:

>>> a[0]=(3, 4, 17, 9.6667, 6.6583, 0.4310, 0)  
>>> b[0]=(4, 4, 12, 8.0, 3.2660, 0.0002, 0)  
>>> fX(a,b)  
Traceback (most recent call last):  
  File "<pyshell#59>", line 1, in <module>  
    fX(a,b)  
  File "<pyshell#52>", line 4, in fX  
    c.append([a[i][x]/float(a[i][x]+b[i][x]) for x in range(len(a[i]))])  
ZeroDivisionError: float division  

我需要一个函数fY(),它可以提供所需的结果而无需对每个值进行强力测试:

>>> a[i]=(3, 4, 17, 9.6667, 6.6583, 0.4310, 0)  
>>> b[i]=(4, 4, 12, 8.0, 3.2660, 0.0002, 0)  
>>> fY()  
>>> [[0.4286, 0.5, 0.5862, 0.5472, 0.6710, 0.9995, 0.0]]  

感谢。

4 个答案:

答案 0 :(得分:4)

def f_cell(a, b):
    try: return a / float(a + b) # EAFP
    except: return 0.0 # Or whatever other value you want for this case.

def fY(a,b):  
    return [
        [f_cell(a_cell, b_cell) for a_cell, b_cell in zip(a_row, b_row)]
        for a_row, b_row in zip(a, b)
    ]

答案 1 :(得分:3)

使用a if x else b三元运算符(相当于C / C ++ / Java表达式x ? a : b)将条件放在列表推导中。这提供了一个有效的Pythonic实现:

def fY(a, b):
    return [[aij/float(aij + bij) if aij+bij != 0 else 0 for aij, bij in zip(ai, bi)]
            for ai, bi in zip(a, b)]

答案 2 :(得分:0)

如果你想在python中这样做,除了对每个元素进行测试之外别无他法。请注意,这根本不会增加您的渐近运行时间,而且非常便宜。它根本不是“蛮力”。

如果您真的非常关心语法,并且根本不关心速度,那么您可以使用特殊的划分规则将每个数字包装在您自己的自定义MyNumber类中。当然,这会产生绝对可怕的开销。

您还可以将计算包装在异常返回try...except的{​​{1}}中,但这相当于“对每个值进行测试”。即使是这种语言的内置功能也相当于“对每个值进行测试”(它只是在背后进行测试)。

答案 3 :(得分:-1)

你可以在不检查分母的情况下制作哈希函数。诀窍是保证分母永远不会为0.你可以通过在分母中按位或者某种方式来做到这一点,确保在分割完成之前至少设置一个非符号位。

以下是样本:

def fY(a,b):  
   c=[]  
   for i in range(len(a)):  
       # Or in a bit to make sure non zero
       c.append([float(a[i][x])/(1 | int(a[i][x]+b[i][x])) for x in range(len(a[i]))])  
   return c  

请注意,分母必须转换为int。至少这是技术,它取决于你是否可以使用它来为你的输入创建一个有意义的哈希函数。上述该技术的示例可能对您(或任何人)有任何好处,也可能不是哈希函数。这是否是一种有助于创建良好可读代码的技术也是另一个问题。