Eigene Klasse für grosse Zahlen (war: probleme mit template)



  • ich bin dabei mir eine BigInt Klasse zu schreiben, die beliebig lang sein kann
    die länge wird in bit angegeben
    hier mal eben der code:

    template <UINT Bits> struct bigint
    { unsigned  m_BigInt : Bits; };
    
    template <UINT Bits> class BigInt
    {
       private:
          unsigned  overflow : 1;    //Überlauf
          unsigned  v_BigInt : 1;    //Vorzeichen
          bigint<Bits>  m_BigInt;    //Mantisse
    
       public:
          BigInt() : overflow(false)
           {}
    
          operator = (int Zahl)
           {
              //-->m_BigInt = (bigint<Bits>)Zahl;<--\\
              overflow = 0;
           }
    };
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    BigInt<2048> a; a = 123456789;
    
    Form1->Caption = IntToStr(sizeof(a)) + " Byte";
    }
    

    bei dieser zeile kommt der fehler

    //-->m_BigInt = (bigint<Bits>)Zahl;<--\\
    

    ich verstehe nicht all zu viel von der ganzen template sache
    kann mit bitte jemand helfen?

    danke!!!



  • Hallo,

    Das liegt hier nicht am template. Damit erstellst du nur ein Bitfeld der angegebenen Größe. Du kannst aber nicht ein int in ein bigibt<> konvertieren, da es hier keinen Konstruktor für int gibt. Entweder du definierst dafür einen oder du änderst den operator= so ab (keine Garantie ob die Klasse noch das macht was sie soll).

    operator = (int Zahl)
    {
    //   m_BigInt.m_BigInt = (<bigint<Bits>)Zahl;
       m_BigInt.m_BigInt = Zahl;
       overflow = 0;
    }
    


  • Supi 😃 Danke Braunstein ... das funzt!

    kannst du mir (für einen nicht so guten c++ programmierer) mal erklähren, warum es möglich ist von den element (m_BigInt) einer klasse (BigInt) auf ein element vom element (m_BigInt.m_BigInt) zuzugreifen?

    und wie muss ich den den konstroktor bauen, wenn ich es möglich machen möchte zuweisungen wie z.B.

    BigInt<2048> a; a = 12345678901234567890123456789;
    

    zu machen?

    wenn mir das noch bitte jemand beantworten kann, bin ich sehr glücklich und ein ganzes stück weiter.



  • Du könntest die Zahl als Zeichenkette übergeben und dann verarbeiten.



  • zu 1.
    Deine Klasse BigInt enthält ja eine Membervariable m_BigInt vom Typ bigint<>. Diese Klasse wiederum hat wieder eine Membervariable m_BigInt. Da beides Strukturen sind und somit hier alles public ist, kannst du logischerweise auch auf die Member der eingebetteten Klassen zugreifen. Das Problem hier entsteht eher durch die ähnlichen (teilweise gleichen Bezeichnungen).

    zu 2.
    Man könnte dein voriges Problem auch dadurch lösen, indem man einen oder mehrere passende Konstruktoren für bigint schreibt. Zum Lösen des ersten Beitrags hier brauchst du einen Defaultkonstruktor sowie einen mit einem int-Parameter.

    Um ein char übernehmen zu können mußt du nun für BigInt einen Zuweisungsoperator für char* schreiben. Wie du den char* in dein bigint bekommst, weiß ich nicht. Wenn ich Langzahlarithmetik brauche verwende ich normalerweise fertige Bibliotheken. Für den BCB eignet sich z.Bsp. NTL. Es gibt zwar auch GMP, allerdings habe ich das mit dem BCB noch nicht übersetzen können (enthält auch ASM).



  • @ Seth_99:
    eigendlich wollte ich es vermeiden, mit ansistrings zu arbeiten ... oder verstehe ich da zeichenketten falsch 😕

    aber trotzdem danke!

    @ Braunstein:
    danke das habe ich verstanden! 😃 ... stimmt in den beiden strukturen die gleiche bezeichnung zu wählen ist wahrlich nicht so klever ... ich frage mich nur warum der c++ builder das element nicht zur auswahl bereitgestellt hat, als ich m_BigInt. eingegeben habe ... da standen nur die anderen struktur elemente (overflow, v_BigInt) oder gibt es dafür auch eine logische erklährung

    wie würde denn so ein defaultkonstruktor aussehen? und wie der mit dem int-parameter?

    die NTL bibliotek habe ich mir zusammen mit zahlreichen opensource biblioteken angesehen ... leider wollte ich mir soche eine bibliotek selbst schreiben und die biblioteken (NTL, GMP, ...) haben mich kein stück weiter gebracht 😞



  • bigint könnte dann so aussehen

    template <UINT Bits>
    struct bigint
    {
         unsigned m_BigInt : Bits;
         bigint(int i = 0) { m_BigInt = i; } // mit default Argument um den default Konstruktor nicht noch schreiben zu müssen
    };
    

    der Zugriff im operator= dann so

    m_BigInt = bigint<Bits>(Zahl);
    


  • thx Braunstein!

    aber das funktioniert nur mit int richtig?

    ich wollte ja auch solche zugriffe möglich machen:
    a = 12345678901234567890123456789;



  • Genau das geht nur für int und mach somit den Sinn einer bigint-Klass zunichte.
    Du müsstest auch einen Konstruktor für char* schreiben. Wie du allerdings deinen char* in deine Klasse bekommst weiß ich auch nicht.
    Hast du einen Algorithmus zum Übertragen der Zahlen in ein Bitfeld?
    Was ich bisher so gesehen habe arbeitet eigentlich intern mit arrays.
    Schau auch mal in diesen Thread
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-110330.html



  • wenn ich ein konstruktor für char* schreiben würde, könnte ich denn die variabeln mit a =

    12345678901234567890123456789;
    

    füllen?

    leider kenne ich keinen algorithmus zum übertragen von zahlen in bitfelder 😞

    ich muss dazuschreiben, ich habe jetzt zum 4. mal angefangen so einen type zu proggen ...

    1. ich habe komplet mit einem ansistring als zahl gearbeitet ... hat auch alles wunderbar funktioniert ... aber sau, sau langsam

    2. ich habe ein array mit ints gemacht und, da der int type 10 stellen hat, aber davon nur 9 nutzbar sind, da die vorderste ziffer maximal 2 sein kann, den type in 9-ner blöcke zerhackt ... hat auch wunderprächtig funktioniert ... aber gefiehl mir immer noch nicht so recht und war bestimmt auch nicht effizent ... aber egal

    3. ich habe versucht binär zu denken und erstmal nur mit bool gearbeitet ... der type war leider nicht schneller als einer der beiden ersten, da es mir nicht möglich war einen 1 bit type u erstellen (oder geht das??)

    4. tja daran arbeite ich ja gerade 😃

    ich muss auch dazu sagen, ich habe wohl schon nahezu das ganze internet durchforstet ... auch viel gefunden und viel neues gelernt! und nicht gerade zeit und mühe gescheut ... aber meine 4. variante geht von der überlegung aus keine liste und kein array zu machen ... leider weiß ich nicht recht ob das möglich ist ... aber ich habe was interessantes dazu gefunden ... darum glaube ich auch das das ganze klappen muss ... ich verstehe den quelltext nur nicht recht ... kann sich das mal - jemand kleveres als mir - anschauen und mir so evtl. weiterhelfen?

    den thread habe ich mir übrigend angesehen aber reichlich wenig verstanden ... vor allem nicht die schlussendliche lösung 😞



  • Was hast dun denn zu bigint mit Bitfeldern gefunden? Kannst du da mal einen Link angeben?



  • ja ... habe ich ausversehen in den bigint ordner gepostet

    der quelltext von dem oben die rede ist ist hier zu finden ...

    escsender.es.funpic.de/LongInt.h



  • Auch hier wird kein Bitfeld verwendet, sondern ein Array auf unsigned short (defaultmäßig).
    Diese Klasse besitzt Konstruktoren für die meisten int-Typen sowie für const char*. In diesem wird wiederum der Zuweisungsoperator (einfaches memcpy) operator* und operator+ verwendet.
    Das ist ein völlig anderes Design als deine Klasse.



  • Weißd du oder jemand anderes wie die datentype int oder long oder double intern aussehen ... das müssten doch auch strucs oder klassen sein oder?

    so ähnlich müsste das doch dann gehen oda???



  • http://de.wikipedia.org/wiki/Integer_(Datentyp)
    http://de.wikipedia.org/wiki/Gleitkommazahl

    bevor du anfängst, solltest du dich gründlich mit der problematik beschäftigen und genau wissen was du willst. nimm dir ein blatt papier und mal dir auf, was wie funktionieren soll. überleg dir, wie und welche daten du übergeben willst. beschäftige dich zuerst mit den grundlagen.

    was für datentypen gibt es? wie sind diese aufgebaut? welchen wertebereich haben sie? wie kann ich beliebig große zahlen verwalten, die über die standardtypen hinausgehen? wie rechne ich mit ihnen? wie gebe ich sie im notfall aus?

    dir sollte klar sein das man kein 1212497135891358971359137589 einfach so eingeben kann, sondern das das nur über einen string funktionieren kann.

    wenn du keine templates verstehst, machs erstmal ohne!
    bitfelder können auch nie grösser als ihr zugrundeliegende datentyp sein!



  • Danke für die infos ...

    aber warum ist den sowas möglich, wenn du sagst: "bitfelder können auch nie grösser als ihr zugrundeliegende datentyp sein"?

    signed mytype : 2048;
    

    es wird eine variable mit 2048 bits erstellt???

    und weiß jemand, wie man die einzelnen bits einlesen oder ausgeben kann ... von mir aus auch erstmal von int oder short??



  • hm... vlei gehts ja doch. bin noch nie auf die idee gekommen, sowas über ein bitfeld zu lösen, da es nicht sehr sinnvoll ist.



  • Dieser Thread wurde von Moderator/in Jansen aus dem Forum VCL/CLX (Borland C++ Builder) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Frage an alle:

    weiß wer, wie ich bei solch einen datentyp

    signed mytype : 2048;
    

    auf die einzelnen bits zugreifen kann, oder sie ändern kann???

    bitte um hilfe!

    Danke



  • so schonmal nicht.
    wird die bitanzahl des zieltyps ueberschritten so wird auf die maximale bitanzahl des verwendeten typs zurueckgesetzt. (koennte bei signed 32 bit sein muss aber nicht).
    ps. einzelne bits lassen sich ohnehin nicht adressieren.


Anmelden zum Antworten