//************************************************************************** // Projekt: // Rechnen mit groáen Ganzzahlen //************************************************************************** // Modul: // mpi.h Headerdatei zur Programmbibliothek // >mpi.cpp Programmbibliothek // main.cpp beispiel Programm, das die Programmbibliothek verwendet //************************************************************************** // Geschichte: // V1.0 08.12.1997 erste Version // V1.1 20.12.1997 umgestellt: malloc -> new; printf -> cout // V1.2 06.01.1998 einlesen langer Zahlen aus text Datei //************************************************************************** // Erstellt von: // Thorsten Milianowitsch 08.12.1997 //************************************************************************** // Beschreibung: // Hier sind die Funktionen zum rechnen mit langen Zahlen implementiert. // Fr ein Beispiel wie man sie verwendet, bitte main.ccp anschauen. //************************************************************************** // Einschr„nkung: // 1. Es k”nne Zahlen mit bis zu 16000 aus Dateien eingelesen werden. // 2. Die gr”sste getestete Zahl hatte 17000 Stellen. // Das Programm l„sst 32000 Stellen zu. Die gr”sste Zahl h„ngt vom // freien Speicher, und dem verwendetem Speichermodell des Compilers ab. // 3. Bei multiplikation sollte erster Parameter die kleinere Zahl // enthalten, da hierbei weniger Speicher ben”tigt wird. // 4. Fhrende Nullen werden beim Ergebnis nicht entfernt. // 5. Die geschwindigkeit h„ngt stark vom Speichermodell des Compilers ab. // Tiny, Small, Medium sind schnell, nicht so grosse Zahlen. // Compact, Large, Huge sind langsam, groessere Zahlen. //************************************************************************** // Bekannte Fehler: // noch keine ;) //************************************************************************** //************************************************************************** // Header Dateien //************************************************************************** #include //#include // fr exit(); #include #include #include "mpi.h" // Makro max() gibt es nur in C nicht in C++ #ifdef __cplusplus int max (int value1, int value2); int max(int value1, int value2) { return ( (value1 > value2) ? value1 : value2); } #endif //************************************************************************** // Implementation der Funktionen //************************************************************************** //************************************************************************** // Speicher fuer eine lange Zahl reservieren //************************************************************************** tlang mpi_getmem(signed int laenge) { tlang tmp; if (laenge>=0) { tmp.lang=laenge; // if ((tmp.zahl=(tzahl *)malloc((tmp.lang+1)*sizeof(tzahl)))==NULL) { // Speicher reservieren if ((tmp.zahl=new tzahl [tmp.lang])==NULL) { tmp.lang=-1; cerr << "\nNicht Genug Speicher!\n\n"; } } else { tmp.lang=-1; tmp.zahl=NULL; cerr << "\nKann keinen negativen Speicher reservieren!\n\n"; } return tmp; } //************************************************************************** // Speicher einer langen Zahl freigeben //************************************************************************** tlang mpi_freemem(tlang tmp) { if ((tmp.lang>=0)&&(tmp.zahl!=NULL)) { delete [] tmp.zahl; // free(tmp.zahl); tmp.zahl=NULL; tmp.lang=-1; } else { tmp.lang=-1; tmp.zahl=NULL; cerr << "\nKonnte Speicher nicht freigeben!\n\n"; } return tmp; } //************************************************************************** // Eine lange Zahl aus einer text Datei lesen //************************************************************************** tlang mpi_lese(const char * name) { tlang tmp,tmp2; int i,handle,bytes; // Datei zum lesen ”ffnen if ((handle=open(name,O_RDONLY | O_TEXT))==-1) { cerr << "\nFehler beim ”ffnen der Datei\n\n"; tmp.zahl=NULL; tmp.lang=-1; return tmp; } // Puffer mit 16000 Stellen erzeugen tmp=mpi_getmem(16000); // Aus Datei in Puffer tmp lesen if ((bytes=read(handle,tmp.zahl,16000))==-1) { cerr << "\nFehler beim lesen der Datei\n\n"; tmp.zahl=NULL; tmp.lang=-1; return tmp; } // Tats„chliche l„nge ermitteln und restlichen Speicher freigeben bytes-=1; tmp2=mpi_getmem(bytes); // Zahl konvertieren for (i=0; i9) { carry=1; tmp.zahl[k]-=10; } else carry=0; } return tmp; } //************************************************ // Zwei lange Zahlen addieren // UND Speicher von erster Zahl freimachen // UND zweite Zahl *10^n // wird fuer multiplikation benoetigt //************************************************ tlang mpi_addiere_free(tlang u, tlang v, int n) { int i=0,j=0,k=0; tlang tmp; signed short int carry=0; signed short int uu,vv; // Addition fast identisch zu normaler Addition tmp=mpi_getmem(max(u.lang,v.lang+n)+1); for (k=0;k9) { carry=1; tmp.zahl[k]-=10; } else carry=0; } u=mpi_freemem(u); return tmp; } //************************************************ // Zwei lange Zahlen subtrahieren // c=mpi_subtrahiere(u,v); // c = u - v; // mit u>=v! //************************************************ tlang mpi_subtrahiere(tlang u, tlang v) { int i=0,j=0,k=0; tlang tmp; signed short int carry=0; signed short int uu,vv; // test ob laenge u < laenge v if (u.lang= laenge v else tmp=mpi_getmem(max(u.lang,v.lang)); if (tmp.lang>=0) { // bei laenge u = lanege v erfolgt test, ob // u > v ist bei der berechnung (dann speicher frei machen!) for (k=0;kuu) { carry=1; uu+=10; } else carry=0; tmp.zahl[k]=uu-vv; } // falls carry nach letztem schritt // war v groesser als u !! if (carry==1) tmp=mpi_freemem(tmp); } else tmp.zahl=NULL; return tmp; } //************************************************ // Eine lange Zahl mit einer stelle multiplizieren //************************************************ tlang mpi_mulkurz(tlang u, tzahl n) { int i=0; tlang tmp; signed short int carry=0; tmp=mpi_getmem(u.lang+1); // wiederhole fr jede Stelle, mit der niedrigsten Stelle beginnend for (i=0; i