| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > инвертировать |
| Автор: Streng 4.5.2006, 07:57 |
| У меня есть 2-х байтовое знаковое целое число. Мне нужно инвертировать в нем каждый четный бит... Как это сделать в с++? |
| Автор: LPBOY 4.5.2006, 08:33 | ||
Самое простое, что у меня получилось, это вот так:
|
| Автор: likehood 4.5.2006, 08:43 | ||
А можно и так:
|
| Автор: LPBOY 4.5.2006, 08:48 | ||
| Действительно... Только разве не так?
|
| Автор: likehood 4.5.2006, 09:00 |
| Если биты отсчитывать с нуля, то да. |
| Автор: Streng 4.5.2006, 10:52 |
| Не получается Например беру число 546-в двоичном виде это 1000100010 В ответе получается 22391 это 101011101110111 |
| Автор: likehood 4.5.2006, 10:59 |
| Как же не получается? Каждый четный бит (крайний правый бит нулеовй, т.е. четный) и вправду инвертирован, а нечетные биты не тронуты. Что тебе не нравится? |
| Автор: Streng 4.5.2006, 11:15 |
| А разьве ответ должен быть не 1101110111? Откуда столько лишних разрядов? |
| Автор: likehood 4.5.2006, 11:25 |
| Инвертируются все два байта, а не только нужная тебе часть числа (твое число дополняется слева нулями до 2-х байт). |
| Автор: Streng 4.5.2006, 13:25 |
| А реально сделать так чтобы инвертировались четные байты только в самом числе? |
| Автор: Fazil6 4.5.2006, 13:31 | ||
главное правильная маска - и инвертируй что хочешь.
абсолютно непонятно что ты хочешь сделать |
| Автор: likehood 4.5.2006, 14:21 |
| Надо сначала узнать где находится крайняя левая еденица, для этого надо последовательно сравнивать число с 0x0001, 0x0002, 0x004, 0x008 и т.д. Затем надо сформировать нужную маску. Только зачем тебе это надо? |
| Автор: likehood 4.5.2006, 15:48 |
| Чем это лучше? Для данного числа пожалуй, но в общем случае - все равно. |
| Автор: LuckLess 4.5.2006, 16:47 |
| baronp, если идти справа налево, но для того чтобы найти левую границу надо будет пройти ВСЕ число. а если идти слева направо, до достаточно найти 1-й установленный разряд. этим и лучше. |
| Автор: sergejzr 4.5.2006, 17:18 | ||
Берёшь своё число, определяешь следущую степень двойки, отнимаешь еденицу и делаешь &
где то так "с лёту" |
| Автор: likehood 4.5.2006, 17:22 | ||
В итоге i содержит номер старшей еденицы числа х, только х конечно же беззнаковое (для операции сравнения), а не знаковое, как было заявлено. |
| Автор: LuckLess 4.5.2006, 17:30 | ||
тоже самое, только быстрее.
|
| Автор: likehood 4.5.2006, 17:44 |
| точно быстрее? мой цикл требует 7 итераций а твой 9 (7+9=16==sizeof(short)) |
| Автор: LuckLess 4.5.2006, 18:13 | ||
| посмотри сам. во первых твой вариант давал неправельный результат. надо было в конце еще 1 битовый здвиг делать в обр. сторону. во вторых твой вариант не может работать с маской unsigned short , так как она переполняеться!! поэтому в примерах маска 4 байта. сделал и себе маску 4 байты , так как если сделать ее 2 , то вычисления становяться медленнее в 4-5 раз, чего и следовало ожидать. вот сравни результаты.
|
| Автор: likehood 4.5.2006, 18:34 |
| На счет переполнения - согласен, лучше маску делать с запасом. Что касается дополнительного сдвига, то это зависит от того, что ты потом с этой маской будешь делать. Нам ведь нужна такая маска: ....10101010, а как ее получить в твоем алгоритме? Ведь не на основе же вычесленной mask'и. Скорость твоего варианта больше (в основном благодаря замене сравнения битовой операцией), это так. Но надо решить всю задачу целиком и сравнить, тогда и посмотрим. ЗЫ !(x&mask) - хорошо придумал, я бы так просто не догадался. |
| Автор: LuckLess 4.5.2006, 18:42 |
| чесно говоря я уже забыл зачем мы ее считали эту маску)) приду домой минут через 30, напишу полностью задачу)) и ты напиши. сравним скорости )) |
| Автор: LuckLess 4.5.2006, 19:30 | ||
вот
|
| Автор: likehood 4.5.2006, 20:57 | ||
мой вариант:
|
| Автор: likehood 4.5.2006, 21:33 | ||||
| Кстати, отличная идея - взять полную маску 0х5555 и обрезать нужное число разрядов. Я то сначала хотел получать эту маску по одному биту в цикле, а тут взял...
...и никаких проблем! Добавлено @ 21:34 Что касается скорости, твой вариант где-то в 1.5 раза быстрее, так что и вправду лучше начинать со старших разрядов. Правда в твоем коде есть одна неточность, из-за чего иногда получается неверный результат. Вот мой вариант твоего кода:
Кстати, только щас заметил пост sergej.z'а, как же я его проглядел? Отличная идея - вычесть из маски 1 - намного красивее моего варианта. Но Func2 все же должен работать быстрее. |
| Автор: LuckLess 4.5.2006, 21:45 | ||
| я чуть переделал. так как с ошибкой было у меня моя функция выиграывет почти в 8 раз
|
| Автор: likehood 4.5.2006, 21:58 |
| Выигрыш, конечно, зависит от компилера и его настроек, но все равно разница очевидна. |
| Автор: maxim1000 4.5.2006, 23:42 | ||
а так?
|
| Автор: Streng 5.5.2006, 00:07 |
| Большое спасибо за помощь!!! |
| Автор: LuckLess 5.5.2006, 00:17 | ||
| maxim1000, результаты
8000 1000 2000 т.е. моя функция пока впереди планеты всей |
| Автор: maxim1000 5.5.2006, 00:40 |
| странно видать, что-то не то с измерением времени у меня Func2 было 480 Func3 - 90 (иначе я б и не написал её сюда) покопаюсь ещё... |
| Автор: maxim1000 5.5.2006, 01:18 |
| А... всё понятно... у меня была включена оптимизация на максимум и я убрал вывод rezult* умный компилятор, наверное, вообще выкинул все вычисления нннда... выходит, моя функция медленнее а я-то думал с умным видом сказать "вот это - метод бисекции" |