Как обработать ошибку деления на ноль при хешировании значений в двух последовательностях

1

У меня есть два списка кортежей с фиксированной длиной. Эта функция вычисляет долю (отношение) для соответствующих элементов (обратите внимание, 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]]  

Спасибо.

  • 0
    Что не так с грубой силой?
  • 1
    [x] for x in range(len(... - это форма повреждения мозга, вызванного такими языками, как C ++. Если вы хотите что-то сделать со всеми элементами списка, сделайте это с элементами списка , а не с элементами временного списка индексов той же длины, которую вы создаете после измерения оригинала. Итеративное добавление к пустому списку также является плохим стилем; вы уже знаете, как использовать понимание списка, поэтому примените ту же технику к внешнему петля.
Теги:
mapping
list-comprehension

4 ответа

3
Лучший ответ

Используйте тернарный оператор a if x else b (эквивалентный выражению 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)]
  • 1
    Это работает и примерно на 10% быстрее, чем другие альтернативы. Спасибо!
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)
    ]
0

Если вы хотите сделать это в python, нет никакого способа помимо теста каждого элемента. Обратите внимание, что это не увеличивает ваше асимптотическое время работы и довольно дешево. Это не "грубая сила" вообще.

Если вам действительно понравился синтаксис, и он не заботился о скорости, вы можете обернуть каждое число в свой собственный класс MyNumber со специальными правилами для деления. Это, конечно же, приведет к совершенно ужасным накладным расходам.

Вы можете также обернуть вычисление в try...except, который возвращает float('nan') в качестве исключения, но это эквивалентно выполнению "теста каждого значения". Даже встроенная функция языка, которая сделала это, эквивалентна выполнению "теста каждого значения" (он просто выполняет тест за спиной).

-1

Ну, вы можете сделать хэш-функцию без проверки знаменателя. Хитрость заключается в том, чтобы гарантировать, что знаменатель никогда не равен 0. Вы можете сделать это побитовым или-во что-то в знаменателе, убедившись, что хотя бы один незнаковый бит установлен до деления.

Здесь пример fY:

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. Это, по крайней мере, техническая возможность, чтобы выяснить, можете ли вы использовать ее для создания значимой хэш-функции для вашего ввода. Приведенный выше пример техники может или не может быть полезен вам (или кому-либо) как хеш-функции. Независимо от того, является ли это методом, который поддается созданию хорошего читаемого кода, также является еще одной проблемой.

  • 0
    почему даунвот, я ответил только на то, что спросили. Я не сказал, что это было хорошо
  • 0
    @ DougT. Благодарю. Это работает и работает в то же время, что и цикл. Тем не менее, мне нужно разрешение, если / когда знаменатель с плавающей запятой.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню