Суть в заголовке. Есть у кого идеи, как написать на С этот код, без ветвлений? Сравнения тоже использовать нельзя, тоесть (a == b) * a не катит. Разрядность a и b одинакова, и известна на этапе компиляции.
А смотрел код после компилятора? Что значит нельзя сравнения? А если будет sub или xor? GCC должен использовать CMOVcc, VC -- SBC + AND Вариант без сравнений (использования флагов) c = a ^ b; c |= c << 1; c |= c << 2; c |= c << 4; c |= c << 8; a = a & c;
Это выдает MSVS. Ни сравнений, ни ветвлений Код (Text): mov eax, a mov ecx, b mov edx, eax sub edx, ecx neg edx sbb edx, edx and eax, edx
Ation Ну вот, а я только хотел решение предложить... Код (Text): #include <intrin.h> // ... unsigned long tmp; a &= -_BitScanForward(&tmp, a-b);
у меня пока есть только такой вариант, но мне он не нравистся умножением ) char c; char offset = sizeof(a) * 8; c = ((a - b) & (1 << offset )) >> offset ; c |= ((b - a) & (1 << offset )) >> offset ; a *= c;
Во: Код (Text): a &= ((signed)((a-b) | (b-a)) >> sizeof(a)*8) ADD: Но всё же, IMHO, лучше оставить изначальный вариант, оставив оптимизацию компилятору.
Чего это не будет? с = 3 ^ 1; // == 2 и далее сдвигами должно получиться ~0 при and с которым другой операнд сохраняется. Эту ошибку исправь сам А если a эквивалентно b то будет 0. То есть > не сравнения?
J0E c = a ^ b ; // 10b c |= c << 1; // 110b ... .. с = 1111 1110, и флаг переполнения. a &= c; // 0 Задача написать именно на С, а там нет средств следить на переполнением, если мне не изменяет память.
Переполнение не нужно. c |= c << 1 | с >> а_какое_число_писать_здесь_не_сказано; Перед тем как искать ошибки в ответах, необходимо сформулировать задачу. На определенном множестве мой алгоритм без ошибочен
Не обращай внимания, то мне показалось что при беззнаковых числах, и установленым последним битом может не работать, и на тестах я это увидел, но потом увидел ошибку в тестах )
Ation На языке Си. Для решения используется операция ! логического НЕ. Код (Text): a &= (!(a^b)-1); // a == b => a^b == 0 => !(a^b) == 1 => (!(a^b) - 1) == 0 => a &= 0 == 0 // a != b => a^b != 0 => !(a^b) == 0 => (!(a^b) - 1) == 0xFFFFFFFF => a &= 0xFFFFFFFF == a На языке ассемблер. Решение аналогичное выше приведенному. Операция сравнения появляется в результате синергии совместного использования инструкций xor и setz. Код (Text): ; eax - содержит значение a ; edx - содержит значение b xor ecx, ecx xor edx, eax ; b^a setz cl ; a == b => b^a == 0 => ZF == 1 => CL = 1 ; a != b => b^a != 0 => ZF == 0 => CL = 0 dec ecx ; a == b => ecx = 0 ; a != b => ecx = 0xFFFFFFFF and eax, ecx Решение на языке Си стало следствием решения на языке ассемблер, но оказалось, что аналогичный код в процессе компиляции создает Borland C++ Builder.
skomarov Операция "не" в результате дает либо TRUE либо FALSE, причем TRUE не обязательно == 1. Поэтому вычитать единицу из результата логической операции не правильно.
google Это замечание следует из стандарта? Код (Text): WG14/N1124 ISO/IEC 9899:TC2 Committee Draft — May 6, 2005 6.5.3 Unary operators 6.5.3.3 Unary arithmetic operators 5. The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).