Umwandlung binär -> Dezimal



  • Hallo,
    ich bin mir Durchaus über die Grundlagen der Umwandlung verschiedener Zahlensysteme bewusst. Das Problem ist folgendes:
    Ich brauche für meine Klassen, die eine Zahl als binären Wert darstellt, eine Funktion, die den Wert der Zahl als string im dezimal Format ausgibt. Die binäre Zahl wird mehr als 32 bzw. 64 stellen haben, weswegen ich die Zahl nicht in einem POD darstellen kann. Ich würde auch nur ungerne den Weg über floating point Variablen gehen.
    Gibt eine Möglichkeit, einen string der Form "1101110101b" in einen string der Form "885d" umzuwandeln, ohne die Grenzen der POD's zu sprengen?



  • Wenn du deiner Klasse beibringst zu dividieren (Integer, mit Rest), dann hast du die Umwandlung in Dezimal ja schon fast fertig.

    Natürlich kannst du es auch andersrum machen: du bastelst dir eine Klasse/Funktion die Zahlen in Dezimaldarstellung addieren kann.
    Dann gehst du die Binärzahl Bit für Bit durch, angefangen beim LSB. Du verwendest zwei dezimale Hilfszahlen: eine für das Ergebnis, und eine für den Wert des aktuellen Bits.
    Den Wert des aktuellen Bits verdoppelst du bei jedem Schleifendurchlauf (einfach auf sich selbst addieren). Und wenn das Bit in der Binärzahl gesetzt ist, addierst du den Wert des aktuellen Bits auf die Ergebnis-Hilfsvariable.

    Sollte auch ziemlich einfach zu implementieren sein.

    Kann leicht sein dass es noch eine einfachere/schnellere Möglichkeit gibt - das ist nicht so 100% mein Spezialgebiet.



  • Also meinst du so etwas?

    std::string dezimal;
    MeineZahl zahl;
    while(zahl)
    {
        dezimal+=(char)((zahl%10)+'0');
        dezimal/=10;
    }
    

    Das wäre eine Lösung. Auf Performance kommt es mir bei der Ein-/Ausgabe nicht an. Allerdings hatte ich die Ausgabe-Funktion als Teil des Debuggens eingeplant, um die algorithmen wie Modulo und Division auf ihre Richtigkeit zu testen 🙂



  • Das wäre die 1. Variante, wenn du dich auf die Division verlässt.

    Die andere Variante kommt ohne Division aus. Braucht wie gesagt bloss eine Funktion die Zahlen in Dezimaldarstellung addieren kann, z.B. zwei std::string oder zwei std::vector<char>. Ist auch denkbar einfach.

    EDIT: es muss natürlich "zahl /= 10" heissen, nicht "dezimal /= 10", aber das ist dir sicher klar (Flüchtigkeitsfehler)



  • Ja, das mit dem dezimal/=10 war ein Flüchtigkeitsfehler 😉

    Ich hab das jetzt mit deinem zweiten Ansatz gelöst (quick and dirty, aber funktioniert 🙂 )

    class test_zahl
    {
       private:
        std::deque<int> zahl;
    
       public:
        test_zahl(int z = 0){zahl.push_back(z);}
    
        std::string to_string() const
        {
            std::string tmp;
            for(int i = zahl.size()-1;i>=0;--i)
                tmp = static_cast<char>((zahl[i]+'0')) + tmp;
            return tmp;
        }
    
        test_zahl& operator+=(const test_zahl& a)
        {
            std::deque<int> tmp ( a.zahl );
            if(zahl.size() < tmp.size())
                for(int i = 0, j = tmp.size() - zahl.size(); i != j;++i)
                    zahl.push_front(0);
            else
                for( int i = 0, j = zahl.size() - tmp.size();i!=j;++i)
                    tmp.push_front(0);
    
            bool uebertrag = false;
            for(std::deque<int>::reverse_iterator tit = zahl.rbegin(), tet=zahl.rend(), ait=tmp.rbegin(); tit!=tet; ++ait,++tit)
            {
                (*tit)+=(*ait);
                if(uebertrag)
                    ++(*tit);
                if(*tit >= 10)
                {
                    (*tit)-=10;
                    uebertrag=true;
                }
                else
                    uebertrag = false;
            }
            if(uebertrag)
                zahl.push_front(1);
            return *this;
        }
    };
    
    //...
    class meine_klasse
    {
        std::string print_as_decimal() const
        {
            std::string bin = lange_binärzahl_als_binärer_string();
            test_zahl tmp(1);
            test_zahl dez;
            for(std::string::const_reverse_iterator it = bin.rbegin(), et = bin.rend();it!=et;++it)
            {
                if(*it=='1')
                    dez+=tmp;
                tmp+=tmp;
            }
            return dez.to_string();
            }
    };
    


  • ohne die Grenzen der POD's zu sprengen

    Was meinst du damit?



  • ich vermute er meint damit dass er mehr bits braucht, als der grösste eingebaute typ bieten kann.

    (ich weiss dass es dann falsch formuliert ist, aber ich bin mir ziemlich sicher dass er das damit sagen wollte. der rest seines postings macht das IMO ziemlich klar.)



  • Das Problem ist, dass meine Klasse eine Zahl darstellt, die 200 oder mehr binär-stellen haben kann. Ausgeben möchte ich diese allerdings dezimal.
    Normalerweise wird das ja einfach so konvertiert:
    0*2^0 + 1*2^1 + 1*2^1 + 0*2^2 ... + 1*2^x
    Würde ich dsa ganze mit unsigned int Lösen, wäre bei 2^32 Schluss. Und den Umweg über long double (wie im Original Post erwähnt) wollte ich nicht gehen.
    Aber dank hustbaer's Lösung ist das Problem ja jetzt gelöst :>



  • Du kannst auch einfach GMP verwenden.


Anmelden zum Antworten