люди помогите пожалуста завтра прогу сдавать очень надо
дан массив unsigned short mas[4] нужно вывести числа в которых четное количество единичных бит препод сказал что надо использовать сдвиг завтра в 9 надо сдать плиз помогите или обьясните как очень надеюсь на помощь!!
битовые операции
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Прошу не сильно бить: решение написано "в лоб". Возможно есть более изящный способ.
Код: Выделить всё
#include <iostream>
bool DoesItHaveOddAmountOfBits(unsigned short uValue)
{
int nBitCount = 0;
while (uValue > 0)
{
if (uValue & 1) ++nBitCount;
uValue >>= 1;
}
return (0 == nBitCount % 2);
}
void main()
{
unsigned short mas[] = {45, 14, 7, 105};
for (int i = 0; i < 4; ++i)
{
if (DoesItHaveOddAmountOfBits(mas[i]))
{
std::cout << mas[i] << std::endl;
}
}
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Есть еще как минимум два на мой взгляд более простых и быстрых решения:
1) Использовать таблицу, где для каждого номера элемента N будет стоять заранее известное значение (1 - если число единиц в номер четное, и 0 - в противном случае). Разумеется целесообразно если размер параметра - 1 байт.
2) В микропроцессоре есть специальный флаг PF, он установливается в 1 если число единичных битов в операнде четное. На самом деле выполнять сотни инструкций вместо одной не рационально, а сдвиги - они вообще относительно медленные операции. Выглядеть будет примерно так:
1) Использовать таблицу, где для каждого номера элемента N будет стоять заранее известное значение (1 - если число единиц в номер четное, и 0 - в противном случае). Разумеется целесообразно если размер параметра - 1 байт.
2) В микропроцессоре есть специальный флаг PF, он установливается в 1 если число единичных битов в операнде четное. На самом деле выполнять сотни инструкций вместо одной не рационально, а сдвиги - они вообще относительно медленные операции. Выглядеть будет примерно так:
Код: Выделить всё
bool DoesItHaveOddAmountOfBits(unsigned short uValue)
{
int res = 0;
asm mov ax, uValue
asm or ax, ax
asm setp byte ptr [res]
return res;
}
It's a long way to the top if you wanna rock'n'roll
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
По условию задачи параметр типа unsigned short, то есть 2 байта." писал(а):Разумеется целесообразно если размер параметра - 1 байт.
У меня тоже была идея написать на асм, но дело в том, что задача алгоритмическая и было оговорено преподавателем, что должен использоваться сдвиг, потому я написал на С++." писал(а):2) В микропроцессоре есть специальный флаг PF, он устанавливается в 1 если число единичных битов в операнде четное.
Позволю себе не согласиться: Правый и левый сдвиг (shr, shl) на один бит - это 2 два процессорных такта, точно также как и add и sub, or, and (в случае, когда оба операнда размещены в регистрах). На самом деле более быстрой операции, чем сдвиг на один бит просто нет." писал(а): ... а сдвиги - они вообще относительно медленные операции
По поводу кода на асме. Я не хотел опускаться до него, но если уж есть готовый код, то можно обсудить

1. Следует использовать extended регистры, работа с ними занимает меньше процессорных тактов на 32 разрядных процессорах.
2. Код or ax, ax. Ничего страшного, просто выглядит путанно. Для установки флагов есть замечательная самодокументирующая себя своим именем команда test, которая делает то же самое что и or, только не меняет регистров. Почему не использовать её, ведь код тогда становится более читабельным? (я не спорю or тоже работает, я сейчас говорю о прозрачности кода)

Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Команды MOV, AND, OR, ADD и пр. еще со времен 386 всегда выполнялась за 1 такт, на 286 уже 2 такта, а вот на современных процессорах до 0.25 тактов (4 инструкции за раз, это при идеальном случае). В то время как SHL/SHR/SAL/SAR и иже с ними за 4 такта (3 такта если находятся в кеше 1 уровня). В моей библиотеке сжатия по хаффману мне удалось отказаться от 2-ух инструкций сдвигов в пользу MOV для табличных расчетов и это дало прирост в 30%. Экспериментально вычисленное время выполнения сдвиговых операций на одноядерном процессоре в среднем составляет 4.8 такта на инструкцию. До сих пор кстати руководствую многими рекомендациями по оптимизации от AMD для 486/586 процессоров и убеждаюсь что они на самом деле правы. Так например не раз убеждался что
быстрее чем loop. Ну и еще довольно много прочих хитростей. А вот самая быстрая команда все таки NOP
И все таки считаю, что данная задача является плохим уроком по работе со сдвиговыми операциями, уж лучше старый добрый bitfuck или хотябы преобразование RGB555 -> RGB888 и обратно
Код: Выделить всё
sub ecx, 1
jnz @xxx

Это старая привычка, со времен когда еще не было инструкции test" писал(а):Код or ax, ax. Ничего страшного, просто выглядит путанно

It's a long way to the top if you wanna rock'n'roll
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
somewhere, ну ты силён, я последний раз программировал на чистом асме в чистом DOS на четвёках" писал(а):Команды MOV, AND, OR, ADD и пр. еще со времен 386 всегда выполнялась за 1 такт, на 286 уже 2 такта, а вот на современных процессорах до 0.25 тактов (4 инструкции за раз, это при идеальном случае). В то время как SHL/SHR/SAL/SAR и иже с ними за 4 такта (3 такта если находятся в кеше 1 уровня). В моей библиотеке сжатия по хаффману мне удалось отказаться от 2-ух инструкций сдвигов в пользу MOV для табличных расчетов и это дало прирост в 30%. Экспериментально вычисленное время выполнения сдвиговых операций на одноядерном процессоре в среднем составляет 4.8 такта на инструкцию.

Ага, это известный факт. Ещё есть очень правильная рекомендация всячески уходить от джампов, например используя сложение с переполнением и вычитание с заёмом (adc, sbb) - при хитро продуманном алгоритме это позволяет в некотрых случаях красиво переделать конструкцию if, в состав которой входит джамп. Вообще там много нюансов есть, к сожалению не все уже помню, так как сейчас нас asm не пишу." писал(а):быстрее чем loop. Ну и еще довольно много прочих хитростей.
Трудно поспорить, я про NOP забыл даже" писал(а):А вот самая быстрая команда все таки NOP

Сейчас ты человека совсем запугаешь, он к нас не придёт больше" писал(а):старый добрый bitfuck или хотябы преобразование RGB555 -> RGB888 и обратно

Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.