Как я могу упростить свое "уравнение" для переключения между 3 и 5?

Переключаться между 0 и 1 легко следующим образом:

 int i = 0;
 i = (++i) % 2; // i = 1
 i = (++i) % 2; // i = 0

Точно так же я обнаружил, что можно "переключаться" между 3 и 5:

 int i = 3;
 i = (((i * 2) - 1) % 3) + 3; // i = 5
 i = (((i * 2) - 1) % 3) + 3; // i = 3

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

5 ответов

Решение

Намного короче:

int i = 3;
i = 8 - i;
i = 8 - i;

И, конечно же, для переключения 0/1 вы должны сделать это:

int i = 0;
i = 1 - i;
i = 1 - i;

И вообще, для a/b переключить, сделать это:

int i = a;
i = (a + b) - i;
i = (a + b) - i;

Как это работает? Что ж, a + b - a является b, а также a + b - b является a,:-D

Другой способ - использовать XOR, потому что a ^ (a ^ b) == b а также b ^ (a ^ b) == a:

int i = 3;
i ^= 3 ^ 5; // i == 5
i ^= 3 ^ 5; // i == 3

Ты мог бы сказать:

i = 3;
i = (i == 5) ? 3 : 5; // it's five now
i = (i == 5) ? 3 : 5; // it's three now
i = (i == 5) ? 3 : 5; // it's five again

Также намного короче:

i = 3;
i ^= 6; // now i = 5
i ^= 6; // now i = 3

Для переключения между двумя числами a а также bвам нужно постоянное значение a XOR b - 1 для вашего первого примера и 6 для второго.

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

#include <stdio.h>

int mapModIntToSequence (int i, int mod, int x[]) {
    return x[i%mod];
}

int main () {
    int i;
    int x[] = {2,7};
    for (i = 0; i < 10; i++) {
        printf ("%d\n",mapModIntToSequence(i,2,x));
    }
}

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

Другие вопросы по тегам