Как проверить, имеет ли значение четность битов или нечетность?

значение имеет четность, если оно имеет четное число 1 бит. Значение имеет нечетную четность, если оно имеет нечетное число 1 бит. Например, 0110 имеет четность и 1110 и нечетность.

Я должен вернуть 1 Если x даже паритета.

int has_even_parity(unsigned int x) {
    return 
}

8 ответов


попробуй:

int has_even_parity(unsigned int x){
    unsigned int count = 0, i, b = 1;

    for(i = 0; i < 32; i++){
        if( x & (b << i) ){count++;}
    }

    if( (count % 2) ){return 0;}

    return 1;
}

valter


x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return (~x) & 1;

предполагая, что вы знаете, что ints 32 бита.


давайте посмотрим, как это работает. Чтобы все было просто, давайте используем 8-битное целое число, для которого мы можем пропустить первые два shift/XORs. Давайте обозначим биты a через h. Если мы посмотрим на наш номер мы видим:

( a b c d e f g h )


первая операция x ^= x >> 4 (помните, что мы пропускаем первые две операции, так как в этом примере мы имеем дело только с 8-битным целым числом). Давайте напишем новые значения каждого бита, объединив буквы, которые XOR'D вместе (например,ab означает, что бит имеет значение a xor b).

( a b c d e f g h ) исключающее или ( 0 0 0 0 a b c d )

результат следующие биты:

( a b c d ae bf cg dh )


в следующей операцией является x ^= x >> 2:

( a b c d ae bf cg dh ) исключающее или ( 0 0 a b c d ae bf )

результат следующие биты:

( a b ac bd АПФ bdf aceg bdfh )

обратите внимание, как мы начинаем накапливать все биты с правой стороны.


следующая операция x ^= x >> 1:

( a b ac bd АПФ bdf aceg bdfh ) исключающее или ( 0 a b ac bd АПФ bdf aceg )

результат следующие биты:

( a ab abc abcd abcde abcdef abcdefgh abcdefgh )


мы накопили все биты в исходном слове, XOR'D вместе, в наименее значимом бит. Таким образом, этот бит теперь равен нулю, если и только если во входном слове было четное число 1 бит (четность). Тот же процесс работает на 32-разрядных целых чисел (но требует двух дополнительных изменений, которые мы пропустили в этой демонстрации).

последняя строка кода просто удаляет все, кроме наименее значимого бита (& 1), а затем переворачивает его (~x). Таким образом, результат равен 1, Если четность входного слова была четной или нулевой в противном случае.


следующий ответ был бесстыдно поднят прямо из бит Twiddling хаки Шон Эрон Андерсон, seander@cs.stanford.edu

вычислить четность слова с умножением

следующий метод вычисляет четность 32-разрядного значения только в 8 операциях >с помощью умножения.

unsigned int v; // 32-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x11111111U) * 0x11111111U;
return (v >> 28) & 1;

также для 64-бит, 8 операций по прежнему достаточно.

unsigned long long v; // 64-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x1111111111111111UL) * 0x1111111111111111UL;
return (v >> 60) & 1;

Эндрю Шапира придумал это и отправил мне на сентябрь. 2 2007,.


на GCC есть встроенная функция для этого:

встроенные функции: int __builtin_parity (unsigned int x)

возвращает паритет x, т. е. число 1-бит в x по модулю 2.

т. е. эта функция ведет себя как has_odd_parity. Инвертировать значение для has_even_parity.

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


основная идея заключается в следующем. Снимите самый правый бит ' 1 ' с помощью x & ( x - 1 ). Скажем, x = 13 (1101) и операция x & ( x - 1 ) is 1101 & 1100 что 1100, обратите внимание, что самый правый бит набора преобразуется в 0.

теперь x is 1100. Операция x & ( x - 1 ) Я.е 1100 & 1011 is 1000. Обратите внимание, что оригинал x is 1101 и после двух операций x & (x - 1) the x is 1000, i.e два бита набора удаляются после двух операций. Если после odd количество операций,x становится нулем, затем его нечетная четность, иначе его четная четность.


обобщить ответ @TypelA для любой архитектуры:

int has_even_parity(unsigned int x) 
{
    unsigned char shift=1;
    while (shift < (sizeof(x)*8))
    {
            x ^= (x>>shift);
            shift<<=1;
    }
    return !(x & 0x1);
}

int parity_check(unsigned x) {
    int parity = 0;
    while(x != 0) {
        parity ^= x;
        x >>= 1;
    }
    return (parity & 0x1);
}

Это довольно старый вопрос, но я отправляю это для тех, кто может использовать его в будущем.

Я не буду добавлять пример этого в c, так как уже есть достаточно хороших ответов.

в случае, если конечный результат должен быть фрагментом кода, который может работать (компилироваться) с программой на c, я предлагаю следующее:

.code

; bool CheckParity(size_t Result)
    CheckParity PROC
    mov     rax, 0
    add     rcx, 0
    jnp     jmp_over
    mov     rax, 1
jmp_over:
    ret
CheckParity ENDP

END

Это фрагмент кода, который я использую для проверки четности вычисленных результатов в 64-битной программе c, скомпилированной с помощью MSVC. Очевидно, что вы можете перенести его на 32bit или другие компиляторы.

это имеет преимущество быть гораздо быстрее, чем с помощью c, и он также использует функциональность процессоров.

в этом примере в качестве входного параметра используется параметр (переданный в соглашении вызова RCX - __fastcall). Он увеличивает его на 0, таким образом, устанавливая флаг четности процессоров, а затем устанавливая переменную (RAX) в 0 или 1, если флаг четности включен или нет.