#python #numpy #numba #binary-operators
#python #numpy #numba #бинарные операторы
Вопрос:
У меня есть список целых чисел, например i=[1,7,3,1,5]
. который я сначала преобразую в список соответствующих двоичных представлений длины L
, например b=["001","111","011","001","101"]
. with L=3
.
Теперь я хочу вычислить, на скольких L
позициях в двоичном представлении есть a 1
, а также ноль 0
. В моем примере результатом будет return=2
, поскольку 1
в третьей (последней) позиции для этих записей всегда есть a . Я был бы рад любому комментарию. Я думаю, в идеале я должен выполнять много операций Xor одновременно. Однако я не уверен, как я могу сделать это эффективно.
Редактировать: Спасибо за множество ответов!! Я должен проверить, какой из них самый быстрый.
Комментарии:
1. Разве ответ не должен быть 3?
2. Обратите внимание, что я откатил ваш вопрос до предыдущей версии, так как вы не должны использовать ответ, чтобы превратить его в следующий вопрос. Рад видеть, что вы опубликовали этот последующий вопрос в обзоре кода
Ответ №1:
Одно из наблюдений заключается в том, что если вы берете И для всех чисел, а также ИЛИ для всех чисел, то XOR этих двух результатов будет иметь 1, где условие выполняется.
Итак:
from functools import reduce
from operator import and_, or_
def count_mixed_bits(lst):
xor = reduce(and_, lst) ^ reduce(or_, lst)
return bin(xor).count("1")
count_mixed_bits([1,7,3,1,5]) # 2
Комментарии:
1. Спасибо за объяснение. Для меня это имеет большой смысл и кажется довольно простым
2. Мне это нужно для работы внутри функции numba. Поэтому я попытался изменить ваш код. Может быть, у вас также есть некоторый опыт работы с numba? Я не уверен, что моя модификация оптимальна.
3. Пожалуйста, не изменяйте свой вопрос, чтобы добавить следующий вопрос. Если у вас есть дополнительный вопрос, рассмотрите возможность публикации нового вопроса, посвященного только этому. Однако, если ваш последующий вопрос касается размера кода и / или эффективности (пока у вас есть рабочий код), рассмотрите возможность публикации его в Code Review
Ответ №2:
Существует numpy.binary_repr
метод, который принимает длину. К сожалению, он не может обрабатывать массивы. Но вместо этого вы можете применить функциональность np.unravel_index
:
def check(arr, lenght):
positions = np.array(np.unravel_index(i, (2,)*lenght))
return positions, np.sum(np.sum(positions, axis=1) != len(arr))
>>> positions, output = check(i, 3)
>>> print(positions)
>>> print(output)
[[0 1 0 0 1]
[0 1 1 0 0]
[1 1 1 1 1]]
2
Ответ №3:
Вот решение, я подозреваю, что оно не очень эффективное, но его легко понять.
Я перебираю цифры и нахожу уникальный набор, затем подсчитываю количество записей с заданной длиной в два:
# create a binary list of 3 elements from input list of integers
i=[1,7,3,1,5]
b=['{0:03b}'.format(x) for x in i]
# loop over the digit position (1,2,3)
cnt=[]
for pos in range(3):
cnt.append(len(set([c[pos] for c in b])))
# cnt now contains a list of either 2(=both 1 and 0 present) or 1 (unique)
# so now we count the number of entries with "2"
result=cnt.count(2)
print (result)
ответ:
2
Ответ №4:
Прежде всего, ваш вопрос помечен как numpy, но ваш массив не является массивом numpy. Вот решение, которое использует numpy:
import numpy as np
def has_zeroes_and_ones_at_index(arr, index_from_right):
shifted_arr = np.right_shift(arr, index_from_right)
has_one_at_index = shifted_arr % 2 == 1
return(True in has_one_at_index and False in has_one_at_index)
arr = np.array([1, 7, 3, 1, 5])
res= has_zeroes_and_ones_at_index(arr, 1)
print(res)
Поскольку числа хранятся в двоичном формате, мы можем использовать сдвиг битов, чтобы переместить все биты чисел вправо, а затем посмотреть на последний бит. Нам не нужно приводить их к двоичному формату раньше.
5 (101) сдвиг вправо на единицу -> 2 (010)
Затем мы создаем маску, чтобы увидеть, какие числа имеют единицу в последнем бите, и возвращаем True, когда в маске есть хотя бы один элемент True и один элемент false .
Комментарии:
1. хорошее использование сдвига битов, я исправил массив в соответствии с вопросом, потому что ваше добавление 2 сделало результат всегда истинным. Кроме того, просто чтобы отметить, что это не совсем отвечает на вопрос, поскольку все еще нужно перебирать позиции битов и подсчитывать количество истин.
Ответ №5:
Для этой задачи вы можете использовать побитовые операторы python.
def find(aList, nn):
return sum(
filter(
lambda bb: bb > 0 ,
(
( 1 <= (sum( (aa amp; 1<<kk) > 0 for aa in aList)) < len(aList) )
for kk in range(nn)
)
)
)
>>> find([1,7,3,1,5],3)
2
>>> find([],3)
0
>>> find([7],3)
0
>>> find([7,1],3)
2
>>> find([7,1,7],3)
2