Как я могу поменять 2 целых числа в C, используя побитовые операторы и битовые манипуляции? - PullRequest
0 голосов
/ 18 марта 2020

У меня возникли проблемы с заменой двух целых чисел с помощью битовых манипуляций. Ниже мой код и консольный ввод / вывод.

#include <stdio.h>

int main() {
    int num1 = 0;
    int num2 = 0;
    int position = 1;

    scanf("%d", &num1);
    scanf("%d", &num2);

    for (int bitindex = 0; bitindex < 8; bitindex++) {
        printf("\nPosition: %d\n", position);
        printf("Number 1: %d\n", num1);
        printf("Number 2: %d\n", num2);
        if ((num1 & position) != (num2 & position)) {
            num1 ^= (num1 << bitindex);
            num2 ^= (num2 << bitindex);
        }
        if (bitindex == 0) {
            position++;
        }
        else {
            position *= 2;
        }
    }

    // printf("Number 1: %d\n", num1);
    // printf("Number 2: %d\n", num2);
}

Вывод:

4 7
Position: 1 Number 1: 4 Number 2: 7
Position: 2 Number 1: 0 Number 2: 0
Position: 4 Number 1: 0 Number 2: 0
Position: 8 Number 1: 0 Number 2: 0
Position: 16 Number 1: 0 Number 2: 0
Position: 32 Number 1: 0 Number 2: 0
Position: 64 Number 1: 0 Number 2: 0
Position: 128 Number 1: 0 Number 2: 0

Возможно, я что-то делаю не так, я довольно плохо знаком с низкоуровневым C программирование. Является ли мой алгоритм изначально ошибочным? Есть ли более простой способ сделать это? Любая помощь и совет приветствуются.

Ответы [ 3 ]

1 голос
/ 18 марта 2020

Является ли мой алгоритм изначально некорректным?

Да. Вам нужно инвертировать бит в определенной позиции.

       num1 ^= position;
       num2 ^= position;

1 * 2 равно 1 + 1. Просто сделайте position *= 2; каждый l oop.

int position = 1;
for (int bitindex = 0; bitindex < 8; bitindex++) {
    if ((num1 & position) != (num2 & position)) {
       num1 ^= position;
       num2 ^= position;
    }
    position *= 2;
}

Есть ли более простой способ сделать это?

Да, поменяйте местами значения с xor, как предлагается в комментариях.

0 голосов
/ 18 марта 2020

Есть ли более простой способ сделать это?

Да, используйте tmp var, он проще и может быть лучше оптимизирован компиляторами.

   int tmp = num1;
   num1 = num2;
   num2 = tmp;
// this swaps the whole value, not just the low 8 bits
// if that's important, see below for bit-difference XOR

Это может иногда компилировать в ноль asm-инструкции; компилятор просто знает, где находится var. Почему люди не используют xor swap?

Возможен простой xor-swap всех значений, но вы никогда не должны использовать его, за исключением редких случаев в рукописном асме. В C всегда используйте вместо tmp var. Какой самый быстрый способ поменять значения в C? спрашивает о xor-swap против обычного swap. По некоторым причинам многие думают, что своп xor может быть более эффективным, и называют это «преждевременной оптимизацией». Это не. Это плохо для компиляторов, а также для людей. Если бы это было более эффективно на некоторой машине, оптимизирующие компиляторы скомпилировали бы нормальные подстановки в подстановки xor в asm; в этом смысл современного оптимизирующего компилятора.


Является ли мой алгоритм по своей сути ошибочным?

Для производительности да.

Для правильности, не ошибочно, но одна ошибка показывает . Вы проверяете бит в bitindex с помощью num1 & position, , но вместо обмена этими битами вы используете num1 << bitindex вместо 1 << bitindex.

Самый первый шаг этого, с bitindex = 0, обнулит оба числа, если одно нечетное, а другое четное (поэтому условие истинно, поскольку их младшие биты различаются). x^x == 0 для всех x.

            // with bit-index = 0
            num1 ^= (num1 << bitindex);   // becomes num1 ^= num1
            num2 ^= (num2 << bitindex);   // becomes num2 ^= num2

Обычно использование сдвинутых num1 и num2 бесполезно.

Также обратите внимание, что ваш position уже равен 1<<bitindex, так что вы можете также просто используйте это, и у вас не будет bitindex.


Вы пытаетесь реализовать обмен по битам, который очень неэффективен. Вы бы когда-нибудь сделали что-нибудь , например, , если бы вы хотели поменять местами только определенный диапазон бит, и вы все равно сделали бы все позиции битов, которые вы хотели, за один шаг, используя маску с эти биты установлены. (Вместо сдвига влево однобитовой маски в al oop.)

С Замена битов в заданной точке между двумя байтами , что объясняет, как работает этот алгоритм:

    unsigned bitdiff = num1 ^ num2;
    bitdiff &= 0xff;               // only swap the low 8 bits
    num1 ^= bitdiff;
    num2 ^= bitdiff;

При замене вашего l oop он может поменять местами 4 и 7.

Или для более крупных входов, таких как 555 и 444, мы получим 700 и 299. (Это
0x22b, 0x1b c => 0x2b c, 0x12b, правильно меняющие младшие 8 бит)

0 голосов
/ 18 марта 2020

простой способ поменять 2 целых числа в C с помощью побитовых операторов:

int main() {
    int i, k;
    scanf("%d%d", &i, &k);
    printf(" value of i=%d k=%d before swapping", i, k);

    i = i ^ k;
    k = i ^ k;
    i = i ^ k;
    printf("value of i=%d k=%d after swapping", i, k);

    return 0;
}

...