it-swarm.com.de

Ändern der Ganzzahl in eine binäre Zeichenfolge

Ich arbeite gerade an einer Simulation des MIPS-Prozessors in C++ für eine Comp-Architekturklasse und habe einige Probleme beim Konvertieren von Dezimalzahlen in Binärzeichen (beidseitig mit Vorzeichen versehen). Alles funktioniert gut bis zum letzten Bit, da mein derzeitiger Algorithmus für int auf 1 << = 31 außerhalb der Grenzen liegt. Sie brauchen nur einen Nudge in die richtige Richtung, um ihn zum Laufen zu bringen. Vielen Dank!

//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;
}

Ich füge auch meinen anderen Algorithmus zur Vollständigkeit hinzu. Ich entschuldige mich für das Fehlen von Kommentaren, aber es ist ziemlich einfach.

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;
 }

Auch wenn jemand gute Möglichkeiten kennt, diese effizienter zu schreiben, würde ich es gerne hören. Ich hatte nur die zwei einführenden Programmierkurse, habe aber mit verschiedenen Techniken gespielt, um zu sehen, wie gut ich ihren Stil mag.

19
Paul Ruiz

Es gibt eigentlich Standard-Einzeiler für diese.

#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();

Sehen Sie sich diesen Lauf als Demo an .

57
Potatoswatter

Ersetzen:

if((mask&a) >= 1)

mit entweder:

if ((mask & a) != 0)

oder:

if (mask & a)

Ihr Problem ist, dass das letzte Bit Ihnen eine negative Zahl gibt, keine positive.

4

Das Problem mit 1 << = 31 wurde in einem anderen Kommentar angesprochen. In Bezug auf das Codestück für die Konvertierung von Zeichenketten -> int haben Sie mehrere Möglichkeiten: 

  • konvertieren Sie den String in einen Stream und verwenden Sie den für den Stream definierten Operator >> (int &)
  • verwenden Sie die Standard-C-Funktion strtol (), die ein Basiswertargument hat (2 für binär).
  • oder wenn Sie die Konvertierung wirklich selbst durchführen möchten, versuchen Sie den folgenden Code:

    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);
    }
    

Beachten Sie, dass dieser Code negative Zahlen im Vergleich zu Ihrem Code unterschiedlich behandelt: In Ihrer Funktion wird das höchstwertige Bit als Signum verwendet. Wenn sich das Bit ganz links im String-Argument für Ihre Funktion nicht an Position 32 befindet (beim Zählen von rechts), führt Ihre Funktion möglicherweise zu falschen Ergebnissen. In dem hier vorgeschlagenen Code gibt es keine spezielle Behandlung von Signum. Wenn Sie jedoch eine 32-stellige Zeichenfolge mit '1' als äußersten linken Wert erhalten, ist das MSB in int-Ergebnis == 1 und die ganze Zahl ist negativ (wie es sein sollte)

0
Pavel Zhuravlev

Ich habe Ihren Code überprüft und konnte keinen Fehler finden. Hier ist der Code, den ich verwendet habe ...

#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
 }

Die Ausgabe lautet 1001110001010110101111010011101 . Sie können dies auf ideone ausführen.

0
Ravi Kumar

Und warum kann man die int nicht einfach in eine uint umwandeln? Dann ist es sehr einfach, die Binärzeichenfolge zu generieren, da Sie sich nicht um das Vorzeichenbit kümmern müssen. Dasselbe gilt für die Konvertierung einer binären Zeichenfolge in eine int: Erstellen Sie sie als uint und wandeln Sie sie in int um:

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;
}

Natürlich können Sie die genannten Optimierungen auch anwenden, z. B. den String-Puffer vorbelegen usw.

Den anderen Weg gehen:

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