C - преобразование в дополнение 2s - PullRequest
2 голосов
/ 06 апреля 2010

Я решил сделать это так

  • номера флип 0 = 1, 1 = 0
  • добавить 1 к LSB
  • если нести, цикл до массива [i] == 0

Но я застрял на последнем пункте; как я могу сказать это в условном цикле?

Ответы [ 5 ]

2 голосов
/ 06 апреля 2010

Вы говорите о расширенной арифметике. Большинство процессоров имеют результаты выполнения и переполнения при каждой операции сложения, но C не предоставляет к ним доступ.

Ваша проблема в том, что числа становятся длиннее, когда они становятся больше. Если вы в последний раз, когда у вас есть, и вам нужно выполнить, вам нужен еще один бит! Это означает, что вам нужно перераспределить массив битов (если вы используете массив).

Конечно, более практичным решением является использование нативных целых чисел, а не отдельных битов, поскольку ваш процессор уже довольно хорошо обрабатывает два дополнения. Затем вы знаете, что добавление одного приводит к выполнению, если исходное число равно (unsigned) -1. Основная проблема остается; если вам нужно выполнить последние unsigned, вам нужно выделить другое.

0 голосов
/ 04 февраля 2013

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

int twos_compliment(unsigned short a)
{
    int result;
    result = 0x0FFF&a;
    result = (((result&0x800)?(0<<11):(1<<11))|((result&0x400)?(0<<10):(1<<10))
            |((result&0x200)?(0<<9):(1<<9))|((result&0x100)?(0<<8):(1<<8))
            |((result&0x080)?(0<<7):(1<<7))|((result&0x040)?(0<<6):(1<<6))
            |((result&0x020)?(0<<5):(1<<5))|((result&0x010)?(0<<4):(1<<4))
            |((result&0x008)?(0<<3):(1<<3))|((result&0x004)?(0<<2):(1<<2))
            |((result&0x002)?(0<<1):(1<<1))|((result&0x001)?0:1));
    return result=result+1;
}
0 голосов
/ 21 ноября 2012

Вы можете сделать 2 дополнения намного проще, как показано ниже:

  • оставайтесь без изменений, пока не найдете 1.
  • сразу после получения первых 1, переверните следующие ближайшие 0 на 1 и 1 на нули и продолжайте делать это. если MSB становится 0, это означает, что произошло переполнение.

Вы можете проверить правильность алгоритма самостоятельно. и реализация должна быть как ниже:

// an 8-bit number
int number[8] = {0, 1, 1, 1, 0, 1, 0, 0};
int i;
bool gotFirstOne = false;

// flip bits after you first encountered an 1
for (i = 0; i < 8; i++)
{
   if(gotFirstOne == false){
       if(number[i] == 1) {
           gotFirstOne = true;
       }
   }
   else {
       number[i] = !number[i];
   }

}

if(number[7] == 0) {
    printf("Overflow occurred");
}

Ура !!!!

0 голосов
/ 06 апреля 2010

Я не совсем уверен, что вы делаете, но, возможно, это поможет:

#define countof(x) (sizeof(x) / sizeof(x[0]))

// an 8-bit number
int byte[8] = {0, 1, 1, 0, 1, 1, 1, 0}; // 1 = on, 0 = off

// flip all bits
for (size_t i = 0; i < countof(byte); ++i)
{
    byte[i] = !byte[i];
}

// add one
for (size_t i = 0; i < countof(byte); ++i)
{
    if (byte[i]) // if on
    {
        byte[i] = 0; // "add 1, reset to zero", and carry (no break)
    }
    else // if off
    {
        byte[i] = 1; // turn on
        break; // nothing to carry, stop adding
    }

}

(Я не знаю, как подтолкнуть вас в правильном направлении, просто не объяснив код, извините. Я думаю, что вы достаточно близко, это все еще полезно.)

Видите ли, когда вы добавляете единицу, если бит уже равен единице, сбрасываете его на ноль и продолжаете вдоль битов. Если бит равен нулю, установите его в единицу, затем выйдите из цикла. (Нечего нести, поэтому мы добавили.)

Надеюсь, это поможет. Кстати, вы заметите, что биты хранятся «назад» в приведенном выше коде. LSB имеет индекс 0.

0 голосов
/ 06 апреля 2010

Таким образом, вы храните свой номер в виде массива целых чисел, которые представляют биты. В приведенном вами примере кода вы забыли увеличить переменную i и проверить, не превышает ли она размер вашего массива.

Вы могли бы написать что-то вроде этого (я предполагаю, что размер массива 5 ):

for (i = 0; i < 5; i++)
{
    if (array1[i] == 1)
        array1[i] = 0;
    else // we found a 0
        array1[i] = 1;
        break;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...