Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: "Пятничная" задачка
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
singlskv
Есть 3 целых числа A,B,C разрядность не принципиальна, но пусть будет байт или uint32.
Допустим что это значения считанные из порта(PIO) в разные моменты времени(типа фильтрация по 3 значениям).
Нужно сформировать из этих 3 чисел 1 число так что бы если в >=2 соответствующих битах 1 то выход 1 иначе 0
те:
Ai = 0 1 1 0
Bi = 0 1 0 1
Ci = 1 0 1 0
-----------------
Ri = 0 1 1 0 <- результат

итд...

нужен самый простой алгоритм...
xemul
Обычное мажорирование
Код
R = (A&B) | (A&C) | (B&C);

слегка съэкономленное
Код
R = (A&B) | ((A|B)&C);

дальше не упрощается.
singlskv
Цитата(xemul @ Mar 31 2009, 21:38) *
Обычное мажорирование
слегка съэкономленное
Код
R = (A&B) | ((A|B)&C);

дальше не упрощается.
Ну да...
Просто было интересно послушать разные варианты... smile.gif
singlskv
Цитата(xemul @ Mar 31 2009, 21:38) *
дальше не упрощается.
Ладно, тогда усложняем, пусть будет 5 чисел A,B,C,D,E
или 7 A,B,C,D,E,F,G...
zzzzzzzz
Простой алгоритм:
Переписываем числа в другие, состоящие из разрядов исходных, например, первое число : А0, В0, С0, ....
Считаем количество единиц в новых числах. Если больше или равно 2х - то пишем в соответствующий бит результата 1, в противном случае 0.
biggrin.gif biggrin.gif biggrin.gif
singlskv
Цитата(zzzzzzzz @ Mar 31 2009, 23:35) *
Простой алгоритм:
biggrin.gif biggrin.gif biggrin.gif
Простой алгоритм ~= экономный алгоритм
Про три числа xemul ответил, интересен вопрос про 5, 7 итд... чисел.
zzzzzzzz
Цитата(singlskv @ Mar 31 2009, 23:48) *
Простой алгоритм ~= экономный алгоритм
Про три числа xemul ответил, интересен вопрос про 5, 7 итд... чисел.
Алгоритм не меняется. Считайте до 5 или 7 - какая разница?
Мажоритарная функция для большого количества длинна, а считать, например, сдвигом числа - довольно просто. Дергаешь флагом и все дела...
singlskv
Цитата(zzzzzzzz @ Mar 31 2009, 23:55) *
Алгоритм не меняется. Считайте до 5 или 7 - какая разница?
Мажоритарная функция для большого количества длинна, а считать, например, сдвигом числа - довольно просто. Дергаешь флагом и все дела...
дык покажите хотя бы для 3 чисел сдвигом
будет лучше чем: R = (A&B) | ((A|cool.gif&C);
?
zzzzzzzz
Цитата(singlskv @ Apr 1 2009, 00:01) *
дык покажите хотя бы для 3 чисел сдвигом
будет лучше чем: R = (A&B) | ((A| cool.gif &C);
?
Лень. Пустая трата времени, имхо. Если Вам не влом, выведите мажоритарную функцию для 7 разрядов. И посмотрите на неё пристально biggrin.gif
SM
А чё, собственно, экономим-то? Время? Память данных? Длину кода? LUT-ы FPGA? Или запасы воды на МКС?
singlskv
Цитата(zzzzzzzz @ Apr 1 2009, 00:30) *
Лень. Пустая трата времени, имхо. Если Вам не влом, выведите мажоритарную функцию для 7 разрядов. И посмотрите на неё пристально biggrin.gif
Вопрос в том, при каком количестве исходных данных выгодне начинать сдвигать биты а при каком
пользовать AND и OR и хитрые их комбинации.
Более того, существуют варианты например сдвига битов через 1(2,3 итд) через умножение,
и тогда можно просто сложением всех чисел получать готовые ответы на >< на конкретных "знакоместах"




Цитата(SM @ Apr 1 2009, 00:46) *
А чё, собственно, экономим-то? Время? Память данных? Длину кода? LUT-ы FPGA? Или запасы воды на МКС?
Остановимся на "Время?"
Все остальное менее актуально...
_Pasha
1.Накладываем маску из 0b001001001... на каждый операнд (для случая 7-ми переменных)

2. Суммируем их

3. Сдвигаем маску.

Итого число операций N*(log(N)+1), что и следовало ожидать smile.gif
singlskv
Цитата(_Pasha @ Apr 1 2009, 01:51) *
1.Накладываем маску из 0b001001001... на каждый операнд (для случая 7-ми переменных)
2. Суммируем их
3. Сдвигаем маску.
Итого число операций N*(log(N)+1), что и следовало ожидать smile.gif
Это так же как вариант с умножением, те проредили биты и сложили.

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

Ну и просто задачка понравилась... smile.gif
xemul
Если правильно посчитал, то минимальная дизъюнктивная форма для функции мажорирования из N элементов будет состоять из
N!/((N+1)/2)!/((N-1)/2)!
дизъюнктивных групп по (N+1)/2 элементов в каждой.
Т.е. для 5 элементов получаем 10 дизъюнктивных групп по 3 элемента, для 7 - 35 групп по 4 элемента.
И (умозрительно) на уровне конъюнкций/дизъюнкций особо это дело не упрощается.
Для подсчета количества единиц в каждом "столбце" битов более удобной может оказаться идея "вертикальных счетчиков".
777777
Цитата(singlskv @ Mar 31 2009, 21:24) *
Есть 3 целых числа A,B,C разрядность не принципиальна, но пусть будет байт или uint32.
Допустим что это значения считанные из порта(PIO) в разные моменты времени(типа фильтрация по 3 значениям).

Если нужна именно фильтрация, то мажорирование не годится, потому что результат может оказатья неожиданным. Лучше уж отсортировать их и взять то, которое окажется посередине.
xemul
Цитата(777777 @ Apr 1 2009, 08:25) *
Если нужна именно фильтрация, то мажорирование не годится, потому что результат может оказатья неожиданным. Лучше уж отсортировать их и взять то, которое окажется посередине.

Если я правильно понял условие задачи singlskv: есть M (независимых) бинарных сигналов (которые, н-р, принимает N-разрядный порт контроллера); нужно по N отсчетам установить мажоритарное состояние каждого сигнала.
_Pasha
Чисто по-эстонски подумал, спустя год: а почему N*(log(N)+1) ?

1.Берем маску  0x5555 и 0xAAAA

2. Каждый элемент проредили, сложили 

Получили N*4 операций. И оно не растет.

Всех с днем Дурака, а меня особенно, потому что я думаю, что самый умный smile.gif
singlskv
Цитата(_Pasha @ Apr 1 2009, 16:13) *
1.Берем маску  0x5555 и 0xAAAA

Для байтовых чисел A,B,C это будет так:
((((A&0x55)+(B&0x55)+(C&0x55))>>1)&0x55) | ((((A&0xAA)>>1)+((B&0xAA)>>1)+((С&0xAA)>>1))&0xAA)

но это сложнее конъюнкций/дизъюнкций
и для 5 чисел наверное так же сложнее
а вот для 7 чисел по маске 001001001 такой вариант видимо уже быстрее
singlskv
для 3 чисел есть такое решение:
Код
R=((((A|B|C)^A^B)&B)^((A|B|C)^A^B)^C) | (((A|B|C)^A^B)&B);

что трансформируется в:
Код
tmp1=(A|B|C)^A^B;
tmp2=tmp1&B;
R=(tmp2^tmp1^C)|tmp2;

оно конечно длиннее для 3 чисел чем конъюнкции/дизъюнкции

но видимо на 7 числах станет уже лучше
xemul
А я про баню...smile.gif
Код
ushort VCntA, VCntB;

void vcounter_2t(ushort x) // count in seq 0, 1, 2, 2...
{
   VCntA |= (VCntB & x);
   VCntB |= x;
}

ushort major_3(ushort *x)
{
   VCntA = VCntB = 0;
   vcounter_2t(*x);
   vcounter_2t(*(x+1));
   vcounter_2t(*(x+2));
   return VCntA;
}

Не проверял, но вроде бы похоже.

major_5, major_7 (нужно добавить VCntС) строятся аналогично.
SM
Если экономим все же время, то переделать схему так, чтобы биты приходили последовательно, в виде A0 B0 ... x0 A1 B1 ... x1 - и потом это слово перекодируем по таблице, в которой записано соответствие выходных битов (пар битов, троек, смотря какая длина чего) входным данным.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.