реализация вычитания с побитовыми сдвигами и приращениями - PullRequest
1 голос
/ 16 августа 2011

Существует ли алгоритм, который можно использовать для вычитания 1 из числа, используя только приращения (++ в C) и сдвиги влево (<< в C)?

РЕДАКТИРОВАТЬ: я используютип unsigned char

Заранее спасибо

Ответы [ 4 ]

4 голосов
/ 16 августа 2011

Вы можете сделать это только с помощью оператора ++. Цикл для UCHAR_MAX итераций. Впрочем, неэффективно:

unsigned char c = 42;
unsigned char i = 0;

while (++i)
{
    ++c;
}
// c is now equal to 41

LIVE DEMO

3 голосов
/ 16 августа 2011

Да. Вам нужно подойти к числу n так, чтобы n mod 255 равнялось originalNumber - 1. Самый простой способ сделать это - добавить 255 к вашему номеру. Это может быть выполнено 255 приложениями оператора ++ или более разумно путем сдвига, пока не потребуются добавления.

Редактировать как запрошено:

unsigned char c = 77;
unsigned char i = 0;


if(c < 128)
{
    i = c;
    c = c << 1;
}
while(++i)
{
    ++c;
}
// c == 76

Я понимаю, что для этого требуется <"оператор", но давайте будем честными, если компьютер может переключаться, он может меньше, чем. В противном случае эта оптимизация невозможна. Имейте в виду, что это также сместит максимум 1 раз, что все же лучше, чем ничего для чисел в диапазоне 3-127. Чтобы сдвинуться дальше, нам понадобится простой старый оператор + для нашего счетчика i. Хотя ... я не знаю ЛЮБОГО компьютера, который не может добавить. </p>

0 голосов
/ 09 марта 2014

Вы можете также реализовать сложение, используя побитовые операторы, а затем соединить это с двумя другими решениями, чтобы получить решение, не требующее оператора "+":

function add(int a, int b) {
   int x, y;
   do {
       x = a & b;
       y = a ^ b;
       a = x << 1;
       b = y;
   } while (a);
   return b;
}
0 голосов
/ 17 августа 2011

Здесь также используется +, так что это не так удивительно, как ответ Пола Р.

unsigned char subtract_one(unsigned char value)
{
    unsigned char addend= 0;

    unsigned char old_addend;

    do
    {
        old_addend= addend;
        addend= addend << 1;
        addend++;
    }
    while (old_addend!=addend); // stops when addend==-1;

    return value + addend;
}
...