Изменение целого числа на двоичную строку цифр

В настоящее время я работаю над симуляцией MIPS-процессора в С++ для класса архитектуры Comp и с некоторыми проблемами, переходящими из десятичных чисел в двоичные (подписанные числа в обоих направлениях). Все работает нормально до самого последнего бита, потому что мой текущий алгоритм выходит за пределы областей для int на 1 <= 31. Просто нужно подтолкнуть в правильном направлении, чтобы запустить его и запустить. Спасибо!

//Assume 32 bit decimal number
string DecimalToBinaryString(int a)
{
    string binary = "";
    int mask = 1;
    for(int i = 0; i < 31; i++)
    {
        if((mask&a) >= 1)
            binary = "1"+binary;
        else
            binary = "0"+binary;
        mask<<=1;
    }
    cout<<binary<<endl;
    return binary;
}

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

int BinaryStringToDecimal(string a)
{
    int num = 0;
    bool neg = false;
    if(a.at(0) == '1')
    {
        neg = true;
        for(int x = a.length()-1; x >= 0; x--)
        {
            if(a.at(x) == '1')
                a.at(x) = '0';
            else a.at(x) = '1';
        }
        a.at(a.length()-1) += 1;
        for(int x = a.length()-1; x >= 0; x--)
        {
            if(a.at(x) == '2')
            {
                if(x-1 >= 0)
                {
                    if(a.at(x-1) == '1')
                        a.at(x-1) = '2';
                    if(a.at(x-1) == '0')
                        a.at(x-1) = '1';
                    a.at(x) = '0';
                }
            }
            else if(a.at(x) == '3')
            {
                if(x-1 >= 0)
                    a.at(x-1) += '2';
                a.at(x) = '1';
            }
        }
        if(a.at(0) == '2')
            a.at(0) = '0';
        else if(a.at(0) == '3')
            a.at(0) = '1';
    }
    for(int x = a.length()-1; x >= 0; x--)
    {
        if(a.at(x) == '1')
            num += pow(2.0, a.length()-x-1);
    }
    if(neg)
        num = num*-1;   
    return num;
 }

Также, если кто-нибудь знает какие-нибудь хорошие способы, чтобы писать о них более эффективно, я бы хотел его услышать. У меня были только два вводных класса программирования, но я играл с разными приемами, чтобы увидеть, насколько мне нравится их стиль.

Ответы

Ответ 1

Для них существуют стандартные однострочные.

#include <bitset>

std::string s = std::bitset< 64 >( 12345 ).to_string(); // string conversion

std::cout << std::bitset< 64 >( 54321 ) << ' '; // direct output

std::bitset< 64 > input;
std::cin >> input;
unsigned long ul = input.to_ulong();

Посмотрите этот прогон как демонстрацию.

Ответ 2

Заменить:

if((mask&a) >= 1)

с помощью:

if ((mask & a) != 0)

или

if (mask & a)

Ваша проблема в том, что последний бит дает отрицательное число, а не положительное.

Ответ 3

Проблема с 1 <= 31 была рассмотрена в других комментариях. Что касается фрагмента кода для преобразования string → int, у вас есть несколько вариантов:

  • конвертировать строку в поток и использовать оператор → (int &), определенный для потока//Коррекция - неважно, что > :-) setbase() модификатор потока не поддерживает значение 2 в качестве аргумента
  • используйте стандартную функцию C strtol(), которая имеет аргумент базового значения (2 для двоичных)
  • или если вы действительно хотите реализовать преобразование самостоятельно, попробуйте следующий код:

    int BinaryStringToDecimal(string a) 
    {
        int Rslt = 0;
        int Mask = 1;
        for (int i = a.length()-1; i >= 0; --i, Mask <<= 1) {
            if (a.at(i) != '0') {
                Rslt |= Mask;
            }
        }
        return (Rslt);
    }
    

Обратите внимание, что этот код относится к отрицательным числам по-разному по сравнению с вашим кодом: в вашей функции бит наивысшего порядка принимается как signum. Если самый левый бит в аргументе строки для вашей функции не находится в позиции 32 (при подсчете справа) ваша функция может привести к неправильным результатам. В коде, предложенном здесь, нет специальной обработки signum. Но если вы получите строку из 32 цифр с "1", так как самый левый из них, MSB в int result будет равен 1, а целое число будет отрицательным (как и должно быть)

Ответ 4

И почему вы не можете просто передать int в uint? Тогда очень легко сгенерировать двоичную строку, потому что вам не нужно беспокоиться о бите знака. То же самое касается преобразования двоичной строки в int: постройте ее как uint, а затем переведите ее в int:

string DecimalToBinaryString(int a)
{
    uint b = (uint)a;
    string binary = "";
    uint mask = 0x80000000u;
    while (mask > 0)
    {
        binary += ((b & mask) == 0) ? '0' : '1';
        mask >>= 1;
    }
    cout<<binary<<endl;
    return binary;
}

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

Идти другим путем:

uint b = 0;
for (int i = 31; i >=0; --i)
{
    b <<= 1;
    if (a.at(i) == '1')
        b |= 1;
}
int num = (int)b;

Ответ 5

Я проверил ваш код и не смог найти никакой ошибки. Вот код, который я использовал...

#include <iostream>
#include <string>
using namespace std;

int main ()
{
  int a=1111165117;
  string binary  ("");
    int mask = 1;
    for(int i = 0; i < 31; i++)
    {
    if((mask&a) >= 1)
        binary = "1"+binary;
    else
        binary = "0"+binary;
     mask<<=1;
 }
 cout<<binary<<endl;
 system("PAUSE");         //optional if not using ideone
 return EXIT_SUCCESS;     //optional if not using ideone
 }

Выход будет 1001110001010110101111010011101. Я могу запустить это на ideone

Ответ 6

Potatoswatter - это, вероятно, путь сюда, но для удовольствия...

template<typename TYPE>
static string binary(TYPE x)
{
   typedef std::make_unsigned<TYPE>::type uTYPE;   
   string str;

   for(uTYPE i = ~((uTYPE)~0 >> 1LL); i; i >>= 1LL)
      str += '0' + ((x & i) > 0);
  return str;
}