Функция для двоичного преобразования - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь преобразовать десятичное значение в двоичное, используя функцию, которую я написал в C ниже.Я не могу понять причину, по которой он печатает 32 ноля, а не двоичное значение 2.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>

int binaryConversion(int num){
    int bin_buffer[32];
    int mask = INT_MIN;
    for(int i = 0; i < 32; i++){
        if(num & mask){
            bin_buffer[i] = 1;
            mask >> 1;
        }
        else{
            bin_buffer[i] = 0;
            mask >> 1;
        }
    }
    for(int j = 0; j < 32; j++){
        printf("%d", bin_buffer[j]);
    }
}


int main(){
    binaryConversion(2);
}

Спасибо

Ответы [ 4 ]

0 голосов
/ 05 марта 2019

INT_MIN - отрицательное число, поэтому при сдвиге вправо с использованием >> старший бит будет по-прежнему 1 вместо нуля, и вы получите mask=11111...111, все биты имеют значение 1.Также значение mask не меняется.лучше использовать >>= вместо.Вы можете попробовать замаскировать 0x1 и сместить действительное значение num вместо mask следующим образом.

int binaryConversion(int num) {
    char bin_buffer[32 + 1];  //+1 for string terminator.
    int shifted = num;
    for (int i = 31; i >= 0; --i, shifted >>= 1) {  //loop 32x
        bin_buffer[i] = '0' + (shifted & 0x1);
    }
    bin_buffer[32] = 0;  //terminate the string.

    printf("%s", bin_buffer);

}
0 голосов
/ 05 марта 2019

Если вы поместите:

printf("%d %d\n", num, mask);

непосредственно в петлю for, вы поймете, почему:

2 -2147483648
2 -2147483648
2 -2147483648
2 -2147483648
:
2 -2147483648

Выражение mask >> 1 делает вправо смещает значение mask, но фактически не присваивает его обратно mask.Я думаю, вы имели в виду использовать:

mask >>= 1;

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

Было бы лучше использовать целые числа без знака, так как оператор >>будет действовать в соответствии с вашими ожиданиями.


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


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

#include <stdio.h>
#include <limits.h>

int binaryConversion(unsigned num) {
    for (unsigned mask = (unsigned)INT_MIN; mask != 0; mask >>= 1)
        putchar((num & mask) ? '1' : '0');
}

int main(void) {
    binaryConversion(2);
    putchar('\n');
}

И только одинОбратите внимание, что значение INT_MIN на самом деле не требуется, чтобы просто был установлен верхний бит.Из-за того, что в настоящее время C допускает обработку дополнения и величины знака (а также дополнения двух) для отрицательных чисел, для INT_MIN может быть установлено значение с несколькими установленными битами (например, -32767).

Есть шаги, чтобы удалить эти малоиспользуемые кодировки из C (C ++ 20 уже пометил это), но для максимальной переносимости вы могли бы вместо этого выбрать следующую функцию:

int binaryConversion(unsigned int num) {
    // Done once to set topBit.

    static unsigned topBit = 0;
    if (topBit == 0) {
        topBit = 1;
        while (topBit << 1 != 0) topBit <<= 1;
    }

    // Loop to process all bits.

    for (unsigned mask = topBit; mask != 0; mask >>= 1)
        putchar(num & mask ? '1' : '0');
}

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

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

0 голосов
/ 05 марта 2019

На ваш основной вопрос уже дан ответ относительно использования >> вместо =>>.Однако с фундаментальной точки зрения нет необходимости буферизовать 1 и 0 в массиве int (например, int bin_buffer[32];), и нет необходимости использовать функцию variadic printf для отображенияint значений, если все, что вы делаете, это вывод двоичного представления числа.

Вместо этого все, что вам нужно, это putchar() для вывода '1' или '0' в зависимости от того, установлен ли какой-либо бит илиЧисто.Вы также можете сделать свою функцию вывода более полезной, указав желаемый размер представления, например, byte (8-бит), word (16-бит) и т. Д.

Например, вы можете сделать:

#include <stdio.h>
#include <limits.h>

/** binary representation of 'v' padded to 'sz' bits.
 *  the padding amount is limited to the number of
 *  bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
 */
void binaryConversion (const unsigned long v, size_t sz)
{
    if (!sz) { fprintf (stderr, "error: invalid sz.\n"); return; }
    if (!v)  { while (sz--) putchar ('0'); return; }

    if (sz > sizeof v * CHAR_BIT)
        sz = sizeof v * CHAR_BIT;

    while (sz--)
        putchar ((v >> sz & 1) ? '1' : '0');
}

int main(){
    fputs ("byte : ", stdout);
    binaryConversion (2, 8);
    fputs ("\nword : ", stdout);
    binaryConversion (2, 16);
    putchar ('\n');
}

, который позволяет установить количество отображаемых битов, например,

Пример использования / Вывод

$ ./bin/binaryconversion
byte : 00000010
word : 0000000000000010

В вашем подходе нет ничего плохого, но может быть более простой способ получить тот же результат.

Дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 05 марта 2019

Две ошибки:

  1. Вы используете >> вместо >>=, так что вы фактически никогда не меняете mask.
  2. Вы не объявили mask как unsigned, поэтому, когда вы сдвигаетесь, он получит расширенный знак, который вам не нужен.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...