Probleme mit int_klasse
-
Hallo!
ich bin dabei eine Klasse zu entwerfen, welche es ermoeglicht, positive Zahlen zu speichern, die groesser (2^32)-1 sind.
Das Problem ist jedoch, dass mein Programm Fehler erzeugt sobald die Zahlen groesser (2^96)-1 werden.
Ich scheine leider unfaehig zu sein den Fehler zu finden, ich hoffe hier kann mir geholfen werden..#include<iostream> #include<iomanip> #include<cmath> using namespace std; class long_unsigned { public: long_unsigned(); long_unsigned(unsigned); inline unsigned giveGR(){return GR;}; inline unsigned give(unsigned op){if(op<GR)return Z[op];else {add(1);return Z[GR-1];}}; void add(unsigned); void set(int,unsigned); void operator+=(long_unsigned); void operator*=(int); void kuerze(); void print(); private: unsigned *Z; unsigned GR; }; long_unsigned::long_unsigned() { Z=new unsigned ; GR=1; Z[0]=0; } long_unsigned::long_unsigned(unsigned op) { Z=new unsigned; GR=1; Z[0]=op; } void long_unsigned::kuerze() { if(GR>1) { if(Z[GR-1]==0) { unsigned *new_Z=new unsigned [GR-1]; for(int i=0;i<GR-2;i++) { new_Z[i]=Z[i]; } delete [] Z; Z=new_Z; GR--; } } } void long_unsigned::print() { for(int i=0;i<GR;i++) for(int j=0;j<32;j++) { if(j==0)cout<<"|"; if(Z[i]&(unsigned)pow(2.,j))cout<<"1"; else cout<<"0"; } cout<<"|"<<endl; } void long_unsigned::set(int nr, unsigned wert) { if(nr>=GR)add(nr-GR+1); Z[nr]=wert; } void long_unsigned::add(unsigned anz) { unsigned *new_Z=new unsigned [GR+anz]; for(int i=0;i<GR;i++) new_Z[i]=Z[i]; delete [] Z; Z=new_Z; for(int i=GR;i<GR+anz;i++) Z[i]=0; GR=GR+anz; } void long_unsigned::operator+=(long_unsigned op) { bool merker=false; int nr=0; do { unsigned act=0; for(int i=0;i<32;i++) { if(merker) { if(Z[nr]&(unsigned)pow(2.,i)&&op.give(nr)&(unsigned)pow(2.,i)) { act=act|(unsigned)pow(2.,i); } else { if(Z[nr]&(unsigned)pow(2.,i)||op.give(nr)&(unsigned)pow(2.,i)) { merker=true; } else { act=act|(unsigned)pow(2.,i); merker=false; } } } else { if(Z[nr]&(unsigned)pow(2.,i)&&op.give(nr)&(unsigned)pow(2.,i)) { merker=true; } else { if(Z[nr]&(unsigned)pow(2.,i)||op.give(nr)&(unsigned)pow(2.,i)) { act=act|(unsigned)pow(2.,i); } } } } Z[nr]=act; if(merker&&nr==GR-1){add(1);} nr++; }while(nr<GR); } void long_unsigned::operator*=(int op) { for(int i=1;i<op;i++)*this+=*this; } int main() { long_unsigned a(pow(2.,2)); for(int i=0;i<150;i++) { a+=a; a.print(); } return 0; }mfg Zarathustra23
-
Ist ja interessant.
Zarathustra23 schrieb:
...mein Programm Fehler erzeugt sobald die Zahlen groesser (2^96)-1 werden....
Welche denn ?

Sorry, ein wenig mehr Information wäre hilfreich. Ansonsten kann ich nur zu einem Debugger raten (ist sowieso eine gute Idee).
Gruß,
Simon2.
-
|00010000000000000000000000000000| |00001000000000000000000000000000| |00000100000000000000000000000000| |00000010000000000000000000000000| |00000001000000000000000000000000| |00000000100000000000000000000000| |00000000010000000000000000000000| |00000000001000000000000000000000| |00000000000100000000000000000000| |00000000000010000000000000000000| |00000000000001000000000000000000| |00000000000000100000000000000000| |00000000000000010000000000000000| |00000000000000001000000000000000| |00000000000000000100000000000000| |00000000000000000010000000000000| |00000000000000000001000000000000| |00000000000000000000100000000000| |00000000000000000000010000000000| |00000000000000000000001000000000| |00000000000000000000000100000000| |00000000000000000000000010000000| |00000000000000000000000001000000| |00000000000000000000000000100000| |00000000000000000000000000010000| |00000000000000000000000000001000| |00000000000000000000000000000100| |00000000000000000000000000000010| |00000000000000000000000000000001| |00000000000000000000000000000000|10000000000000000000000000000000| |00000000000000000000000000000000|01000000000000000000000000000000| |00000000000000000000000000000000|00100000000000000000000000000000| |00000000000000000000000000000000|00010000000000000000000000000000| |00000000000000000000000000000000|00001000000000000000000000000000| |00000000000000000000000000000000|00000100000000000000000000000000| |00000000000000000000000000000000|00000010000000000000000000000000| |00000000000000000000000000000000|00000001000000000000000000000000| |00000000000000000000000000000000|00000000100000000000000000000000| |00000000000000000000000000000000|00000000010000000000000000000000| |00000000000000000000000000000000|00000000001000000000000000000000| |00000000000000000000000000000000|00000000000100000000000000000000| |00000000000000000000000000000000|00000000000010000000000000000000| |00000000000000000000000000000000|00000000000001000000000000000000| |00000000000000000000000000000000|00000000000000100000000000000000| |00000000000000000000000000000000|00000000000000010000000000000000| |00000000000000000000000000000000|00000000000000001000000000000000| |00000000000000000000000000000000|00000000000000000100000000000000| |00000000000000000000000000000000|00000000000000000010000000000000| |00000000000000000000000000000000|00000000000000000001000000000000| |00000000000000000000000000000000|00000000000000000000100000000000| |00000000000000000000000000000000|00000000000000000000010000000000| |00000000000000000000000000000000|00000000000000000000001000000000| |00000000000000000000000000000000|00000000000000000000000100000000| |00000000000000000000000000000000|00000000000000000000000010000000| |00000000000000000000000000000000|00000000000000000000000001000000| |00000000000000000000000000000000|00000000000000000000000000100000| |00000000000000000000000000000000|00000000000000000000000000010000| |00000000000000000000000000000000|00000000000000000000000000001000| |00000000000000000000000000000000|00000000000000000000000000000100| |00000000000000000000000000000000|00000000000000000000000000000010| |00000000000000000000000000000000|00000000000000000000000000000001| |00000000000000000000000000000000|00000000000000000000000000000000|10000000000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|01000000000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00100000000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00010000000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00001000000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000100000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000010000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000001000000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000100000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000010000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000001000000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000100000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000010000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000001000000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000100000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000010000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000001000000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000100000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000010000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000001000000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000100000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000010000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000001000000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000100000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000010000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000001000000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000000100000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000000010000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000000001000| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000000000100| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000000000010| |00000000000000000000000000000000|00000000000000000000000000000000|00000000000000000000000000000001| *** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0804b008 *** ======= Backtrace: ========= /lib/tls/i686/cmov/libc.so.6[0xb7ce6a85] /lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7cea4f0] /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7eb1b11] /usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xb7eb1b6d] ./a.out(__gxx_personality_v0+0x382)[0x8048af6] ./a.out[0x8049235] ./a.out[0x8048ca9] ./a.out[0x80490f8] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7c91450] ./a.out(__gxx_personality_v0+0x3d)[0x80487b1] ======= Memory map: ======== 08048000-0804a000 r-xp 00000000 08:12 8831496 /mnt/no2/tino/QUELLTEXTE/AAA_neues/a.out 0804a000-0804b000 rw-p 00001000 08:12 8831496 /mnt/no2/tino/QUELLTEXTE/AAA_neues/a.out 0804b000-0806c000 rw-p 0804b000 00:00 0 [heap] b7b00000-b7b21000 rw-p b7b00000 00:00 0 b7b21000-b7c00000 ---p b7b21000 00:00 0 b7c7a000-b7c7b000 rw-p b7c7a000 00:00 0 b7c7b000-b7dc4000 r-xp 00000000 08:01 689466 /lib/tls/i686/cmov/libc-2.7.so b7dc4000-b7dc5000 r--p 00149000 08:01 689466 /lib/tls/i686/cmov/libc-2.7.so b7dc5000-b7dc7000 rw-p 0014a000 08:01 689466 /lib/tls/i686/cmov/libc-2.7.so b7dc7000-b7dca000 rw-p b7dc7000 00:00 0 b7dca000-b7dd4000 r-xp 00000000 08:01 671809 /lib/libgcc_s.so.1 b7dd4000-b7dd5000 rw-p 0000a000 08:01 671809 /lib/libgcc_s.so.1 b7dd5000-b7df8000 r-xp 00000000 08:01 689474 /lib/tls/i686/cmov/libm-2.7.so b7df8000-b7dfa000 rw-p 00023000 08:01 689474 /lib/tls/i686/cmov/libm-2.7.so b7dfa000-b7ee2000 r-xp 00000000 08:01 18925 /usr/lib/libstdc++.so.6.0.9 b7ee2000-b7ee5000 r--p 000e8000 08:01 18925 /usr/lib/libstdc++.so.6.0.9 b7ee5000-b7ee7000 rw-p 000eb000 08:01 18925 /usr/lib/libstdc++.so.6.0.9 b7ee7000-b7eee000 rw-p b7ee7000 00:00 0 b7efd000-b7eff000 rw-p b7efd000 00:00 0 b7eff000-b7f00000 r-xp b7eff000 00:00 0 [vdso] b7f00000-b7f1a000 r-xp 00000000 08:01 671763 /lib/ld-2.7.so b7f1a000-b7f1c000 rw-p 00019000 08:01 671763 /lib/ld-2.7.so bfdd7000-bfdec000 rw-p bffeb000 00:00 0 [stack] AbortedDas Programm faengt bei 2^4 oder so an, und verdoppelt dann immer... wenn 32bit voll sind und bei der Addition noch ein uebertrag bleibt, werden einfach neue 4 byte angefordert.
Ab 2^96 kommt er dann nich mehr auf seinen Arbeitsspeicher fit, wie die ausgabe erahnen laesst...mfg
-
Es liegt bestimmt nicht daran, aber eine Kleinigkeit: Du forderst im Konstruktor mit "new unsigned" Speicher an, gibst ihn aber mit "delete**[]**" frei, also am Besten überall mit "new[]" anfordern.
edit: Kann's sein, dass du in der Methode "operator+=" gar nicht den Speicher vergrößerst, wenn's erforderlich ist?
-
Erster Punkt bachte mich nicht weiter, haette mich auch gewundert wenn der g++ daran gescheitert waere^^
zweitne Punkt kann ich leider nur dementieren
Zeile 127:
if(merker&&nr==GR-1){add(1);}(Wenn Uebertrag und kein Platz mehr, neuen Speicher anfordern)
mfg
-
Zarathustra23 schrieb:
Erster Punkt bachte mich nicht weiter, haette mich auch gewundert wenn der g++ daran gescheitert waere^^
Wenn die Klasse portabel sein soll (also auch auf anderen Plattformen/Compilern laufen soll), würde ich schon sauber programmieren.
Zarathustra23 schrieb:
zweitne Punkt kann ich leider nur dementieren
Oh stimmt, das "add" haste aber auch gut versteckt

-
Deine Klasse besitzt einen Zeiger auf allokierten Speicher, aber keinen selbstgeschriebenen Copy-ctor oder Zuweisungsoperator. Der Copyctor wird zumindest für das Funktionsargument von += benötigt. Zwar sollte dies wohl ohnehin besser eine Referenz auf const sein - trotzdem ist die normale Kopierinfrastruktur wichtig. Generell würde ich empfehlen, diese bei jeder neuen Klasse als erstes zu implementieren - dann kann man das nicht vergessen. Es gibt noch eine ganze Reihe anderer Fehler, aber die sind nicht ursächlich für den Absturz.
Nebenbei: das bitweise addieren ist reichlich umständlich. Du solltest dir zunutze machen, dass vorzeichenlose Arithmetik nicht überlaufen kann.c = a + b + carry; carry = carry ? c <= a : c < a;
-
Vielleicht kannst Du Dir hier etwas abschauen:
http://mattmccutchen.net/bigint/