Nytro Posted March 16, 2011 Report Posted March 16, 2011 O parte a unui mic proiect pentru scoala presupunea sa adun niste numere mari. Am decis sa folosesc siruri de caractere pentru memorarea acestor numere si sa scriu o functie care sa le adune, returnand un sir constand in suma celor doua.Ma gandesc ca poate fi utila, cine stie cand.// (c) Ionut Gabriel Popescu 2015// Functie ce preia ca parametri 2 siruri de caractere, NUMERE si returneaza suma lor ca sirchar* aduna_siruri(const char *sir1, const char *sir2){ // Determinam rapid lungimile sirurilor int lun_1 = 0, lun_2 = 0, ultim; while(sir1[lun_1++]); while(sir2[lun_2++]); // Pozitia ultimei cifre ultim = lun_1 > lun_2 ? lun_1 : lun_2; ultim++; // Alocam spatiu pentru noul sir char *suma_s = new char[ultim]; suma_s[(--ultim)--] = '\0'; int transport = 0, i, j; i = lun_1 - 1; j = lun_2 - 1; // Facem adunarea cat timp avem acelasi nr. de cifre int mic = i < j ? i : j; i--; j--; while(mic--) { // Daca suma e 0-9 if(sir1[i] + sir2[j] + transport < 106) { suma_s[ultim--] = sir1[i] + sir2[j] + transport - 48; // Cifra din suma celor 2 cifre transport = 0; } // Daca depaseste 9 else { suma_s[ultim--] = sir1[i] + sir2[j] + transport - 58; // Cifra din suma celor 2 cifre transport = 1; } i--; j--; } i++; j++; // Pentru numar egal de cifre, daca avem sau nu transport if(i == 0 && j == 0) { if(transport) suma_s[0] = '1'; else { // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; delete[] suma_s; return final; } } //Completam cu cifrele numarului cu mai multe cifre if(i) { // Parcurgem sirul ` si nu uitam de transport while(i) { i--; // Daca e 0 if(sir1[i] + transport == 58) { suma_s[ultim--] = sir1[i] + transport - 10; transport = 1; } else { suma_s[ultim--] = sir1[i] + transport; transport = 0; } } // Daca avem transport, pe prima pozitie avem 1 if(transport) suma_s[0] = '1'; else { // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; delete[] suma_s; return final; } } else if(j) { // Parcurgem sirul 2 si nu uitam de transport while(j) { j--; // Daca e 0 if(sir2[j] + transport == 58) { suma_s[ultim--] = sir2[j] + transport - 10; transport = 1; } else { suma_s[ultim--] = sir2[j] + transport; transport = 0; } } // Daca avem transport, pe prima pozitie avem 1 if(transport) suma_s[0] = '1'; else { // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; delete[] suma_s; return final; } } // Returnam suma return suma_s;}Codul mai lizibil aici:[C++] Nytro - Pastebin.comMi-a luat vreo 2-3 ore sa scap de o gramada de probleme stupide. Ex.cout<<aduna_siruri("88", "999")<<endl;Ar trebui sa functioneze corect pentru toate cazurile posibile, daca ai incerca sa faci o astfel de functie ai vedea cate batai de cap poate sa iti dea, sunt multe cazuri posibile.Nu cred ca e cea mai optima si cea mai bine scrisa, dar isi face treaba, indiferent de lungimea sirurilor de caractere. Doar ca e necesar ca sirurile sa contina numai cifre. Quote
tiodr Posted March 16, 2011 Report Posted March 16, 2011 eu pt sume de numere mari care nu se put calcula faceam asa :-daca un numar era mai mare ca celelalt la cel mai mic ii puneam in fata cateva 0-uri pentru a le face egale ca numar de caractere;-dupa aceea imparteam numarul in vectori;-intr-un final adunam a cu b;-dupa aceea recompuneam numarul si asta e;si chestia asta sa facea cam in 20 de linii, in niciuin caz 159:) dar asta doar ca un btw Quote
Robert1995 Posted March 16, 2011 Report Posted March 16, 2011 (edited) Nytro are si comentarii la fiecare operatie + ca lasa loc intre operatii sa poate sa vada de unde vin erorile si chiar el a spus Nu cred ca e cea mai optima si cea mai bine scrisa, dar isi face treaba, indiferent de lungimea sirurilor de caractere. Doar ca e necesar ca sirurile sa contina numai cifre. Edit : tiodr , da asa am facut si eu , in 30 de linii cu tot cu comentarii , parca la campion.edu.ro anul trecut a fost o problema in genul astaEdit 2 : Gata scuze ti-am corectat numele , ma apuc sa scriu inca o varianta la asta Edited March 17, 2011 by Robert1995 Quote
tiodr Posted March 16, 2011 Report Posted March 16, 2011 Edit : tiodar , da asa am facut si eu , in 30 de linii cu tot cu comentarii , parca la campion.edu.ro anul trecut a fost o problema in genul astatiodr e nick-ul meu ma:| chiar nu vedeti?tiodr Quote
Nytro Posted March 16, 2011 Author Report Posted March 16, 2011 Si functiona bine pentru cazurile ca:3888 + 333 sau 9988 + 444 sau 64 + 36 care depaseau? As fi curios sa vad o alta implementare. Quote
begood Posted March 24, 2011 Report Posted March 24, 2011 (edited) ati studiat careva implementarea radicalului de ordin 2 -> n pe "lucrul cu numere mari" ?daca da, pm me ca vreau sa discutam ceva.LE: ce tare, anul trecut cand eram interesat de problema asta, nu era implementat decat pentru adunare, scadere inmultire si impartire, acum a aparut si radacina cubica -> ordin n. bravos infoarena.LE2: 1. cine-i interesat sa facem un calculator cu interfata GUI, preferabil cross-platform (in java de exemplu) pentru numere mari ?2. cine-i interesat sa facem un calculator cu display pe cat mai multi digiti, folosind algoritmii de la infoarena pe care-i adaptam pentru circuit ?(am nevoie pentru calculul lui pi, numere prime si lucrul cu numere "lungi" in general) (de la >64 cifre)ps1 : circuitul va fi "opensource", voi posta pe blog tot, de la ideea initiala pana la bug-uri, workarounds, etc.ps2: vreau sa implementez un algoritm de determinare a divizorilor primi in O(1), metoda originala gasita de subsemnatul.PM me. Edited March 24, 2011 by begood Quote
tiodr Posted March 24, 2011 Report Posted March 24, 2011 @begood ai prea mult timp liber:dps: nu o lua ca pe ceva rau:) Quote
l3asketballplayer Posted March 24, 2011 Report Posted March 24, 2011 @begood da-mi pmNitro, codul tau e mult prea lung si nu cred ca e foarte eficient. Citeste articolul de pe infoarena Quote
begood Posted March 26, 2011 Report Posted March 26, 2011 @begood ai prea mult timp liber:dps: nu o lua ca pe ceva rau:)correction : am avut prea mult timp liber. Quote
Paul4games Posted March 27, 2011 Report Posted March 27, 2011 @Nytro uite aici alta implementare in delphi(si ai avut dreptate in legatura cu erorile,mi-a luat ceva timp pana sa ajung la functia asta)[Delphi] Adunare - Pastebin.com@tiodr as fi interesat sa vad functia asta scrisa in 20 de lini de codbtw functia mea nu este optimizata,am vrut sa o optimizez acum dar sunt obosit si dupa cateva modificari iara nu mai functiona calumea Quote
Nytro Posted March 27, 2011 Author Report Posted March 27, 2011 Nu e chiar atat de mare nici functia mea, as putea scapa de // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; delete[] suma_s; return final;Am vrut sa returnez un pointer frumos la char.Oricum, scoateti comentariile de la mine si o sa vedeti ca nu mai e atat de infricosatoare. Quote
Paul4games Posted March 27, 2011 Report Posted March 27, 2011 (edited) Acuma am vazut ca am gresit citind nr,nr1 ca integer,am modificat sursa si acum citesc ca strings:[Delphi] Adunarea - Pastebin.com@nytro nu am citit functia ta pentru ca nu prea inteleg C++ Edited March 27, 2011 by Paul4games Quote
Nytro Posted March 27, 2011 Author Report Posted March 27, 2011 A, asa ca idee, eu nu am folosit strlen(), am facut asta manual, tot aveam posibilitatea, asa am putina viteza in plus. Desi e scris stupid, cred ca e destul de rapida functia mea. Quote
Paul4games Posted March 27, 2011 Report Posted March 27, 2011 Dupa cum am spus nu este optimizata functia mea,acum nu mai am chef sa stau sa o optimizez,poate alta data cand ma plictisesc! Quote
Nytro Posted March 27, 2011 Author Report Posted March 27, 2011 La mine e vorba de un proiect mai mare, dar nu am avut timp si nu mi-am dat interesul sa fac prea multe: Nytrp - Pastebin.com[/url][code]/* Nume: Popescu Ionut Gabriel Tema: Numere reale mari Continut: Definitia clasei pentru lucrul cu numere reale mari*//* Observatie nr : 0.222 - double nr_prec : 0.2219999999999942 - reprezentarea sa (precizie 16) Sau: nr : 0.456 nr_prec : 0.4560000000000031 - reprezentarea sa (precizie 16)*/// Prevenire multi-incluziune#ifndef BIGREAL_H_INCLUDED#define BIGREAL_H_INCLUDED// Pentru supraincarcare << si >>#include <iostream>#include <fstream>// O cifra ce foloseste 4 biti in loc de 8// Mai putina memorie folosita (1/2)// Pentru posibile implementari ulterioarestruct cifra_mica{ unsigned char c: 4;};// Macro, daca e cifra#define e_cifra(x) (x >= '0' && x <= '9' ? 1 : 0)// Modul de depanare#define DEBUG 0// Definitia claseiclass BigReal{ private: char *intreg, *zecimal; // Vectori pentru cifre bool semn; // Daca numarul e pozitiv sau negativ // Metode ajutatoare char* intreg_la_sir(int x); // Convertire de la intreg la sir de caractere char* zecimala_la_sir(double x); // Convertire parte zecimala la sir char* aduna_siruri(const char *sir1, const char *sir2); // Adunare 2 siruri de caractere public: // Constructori si destructor BigReal(); // Constructor fara parametri BigReal(int x); // Constructor cu parametru int BigReal(double x); // Constructor cu parametru double BigReal(const char *sir); // Constructor cu parametru sir BigReal(BigReal &ob); // Constructor de copiere ~BigReal(); // Destructor // Supraincarcare operator + BigReal& operator + (int x); // BigReal + int BigReal& operator + (double x); // BigReal + double BigReal& operator + (const char *sir); // BigReal + sir BigReal& operator + (BigReal &ob); // BigReal + BigReal friend BigReal& operator + (int x, BigReal &ob); // int + BigReal friend BigReal& operator + (double x, BigReal &ob); // double + BigReal friend BigReal& operator + (const char *sir, BigReal &ob); // sir + BigReal // Supraincarcare operator binar - BigReal& operator - (int x); // BigReal - int BigReal& operator - (double x); // BigReal - double BigReal& operator - (const char *sir); // BigReal - sir BigReal& operator - (BigReal &ob); // BigReal - BigReal friend BigReal& operator - (int x, BigReal &ob); // int - BigReal friend BigReal& operator - (double x, BigReal &ob); // double - BigReal friend BigReal& operator - (const char *sir, BigReal &ob); // sir - BigReal // Supraincarcare operatori unar - si + BigReal& operator - (); // - BigReal BigReal& operator + (); // + BigReal // Supraincarcare operator binar * BigReal& operator * (int x); // BigReal * int BigReal& operator * (double x); // BigReal * double BigReal& operator * (const char *sir); // BigReal * sir BigReal& operator * (BigReal &ob); // BigReal * BigReal friend BigReal& operator * (int x, BigReal &ob); // int * BigReal friend BigReal& operator * (double x, BigReal &ob); // double * BigReal friend BigReal& operator * (const char *sir, BigReal &ob); // sir * BigReal // Supraincarcare operator / BigReal& operator / (int x); // BigReal / int BigReal& operator / (double x); // BigReal / double BigReal& operator / (const char *sir); // BigReal / sir BigReal& operator / (BigReal &ob); // BigReal / BigReal friend BigReal& operator / (int x, BigReal &ob); // int / BigReal friend BigReal& operator / (double x, BigReal &ob); // double / BigReal friend BigReal& operator / (const char *sir, BigReal &ob); // sir / BigReal // Supraincarcare operator < BigReal& operator < (int x); // BigReal < int BigReal& operator < (double x); // BigReal < double BigReal& operator < (const char *sir); // BigReal < sir BigReal& operator < (BigReal &ob); // BigReal < BigReal friend BigReal& operator < (int x, BigReal &ob); // int < BigReal friend BigReal& operator < (double x, BigReal &ob); // double < BigReal friend BigReal& operator < (const char *sir, BigReal &ob); // sir < BigReal // Supraincarcare operator <= BigReal& operator <= (int x); // BigReal <= int BigReal& operator <= (double x); // BigReal <= double BigReal& operator <= (const char *sir); // BigReal <= sir BigReal& operator <= (BigReal &ob); // BigReal <= BigReal friend BigReal& operator <= (int x, BigReal &ob); // int <= BigReal friend BigReal& operator <= (double x, BigReal &ob); // double <= BigReal friend BigReal& operator <= (const char *sir, BigReal &ob); // sir <= BigReal // Supraincarcare operator > BigReal& operator > (int x); // BigReal > int BigReal& operator > (double x); // BigReal > double BigReal& operator > (const char *sir); // BigReal > sir BigReal& operator > (BigReal &ob); // BigReal > BigReal friend BigReal& operator > (int x, BigReal &ob); // int > BigReal friend BigReal& operator > (double x, BigReal &ob); // double > BigReal friend BigReal& operator > (const char *sir, BigReal &ob); // sir > BigReal // Supraincarcare operator <= BigReal& operator >= (int x); // BigReal >= int BigReal& operator >= (double x); // BigReal >= double BigReal& operator >= (const char *sir); // BigReal >= sir BigReal& operator >= (BigReal &ob); // BigReal >= BigReal friend BigReal& operator >= (int x, BigReal &ob); // int >= BigReal friend BigReal& operator >= (double x, BigReal &ob); // double >= BigReal friend BigReal& operator >= (const char *sir, BigReal &ob); // sir >= BigReal // Supraincarcare operator == BigReal& operator == (int x); // BigReal == int BigReal& operator == (double x); // BigReal == double BigReal& operator == (const char *sir); // BigReal == sir BigReal& operator == (BigReal &ob); // BigReal == BigReal friend BigReal& operator == (int x, BigReal &ob); // int == BigReal friend BigReal& operator == (double x, BigReal &ob); // double == BigReal friend BigReal& operator == (const char *sir, BigReal &ob); // sir == BigReal // Supraincarcare operator != BigReal& operator != (int x); // BigReal != int BigReal& operator != (double x); // BigReal != double BigReal& operator != (const char *sir); // BigReal != sir BigReal& operator != (BigReal &ob); // BigReal != BigReal friend BigReal& operator != (int x, BigReal &ob); // int != BigReal friend BigReal& operator != (double x, BigReal &ob); // double != BigReal friend BigReal& operator != (const char *sir, BigReal &ob); // sir != BigReal // Supraincarcare operator = BigReal& operator = (int x); // BigReal = int BigReal& operator = (double x); // BigReal = double BigReal& operator = (const char *sir); // BigReal = sir BigReal& operator = (BigReal &ob); // BigReal = BigReal // Supraincarcare operatori cast operator int (); // int = BigReal operator double (); // double = BigReal operator char* (); // sir = BigReal // Supraincarcare << si >> pentru cout si cin friend std::ostream& operator << (std::ostream &flux, BigReal &ob); // cout << BigReal friend std::istream& operator >> (std::istream &flux, BigReal &ob); // cin >> BigReal // Supraincarcare operator ++ BigReal& operator ++ (); // ++ BigReal BigReal& operator ++ (int x); // BigReal ++ // Supraincarcare operator -- BigReal& operator -- (); // -- BigReal BigReal& operator -- (int x); // BigReal -- // Functii pentru acces la date, publice, inline char* intoarce_intreg() { return intreg; } // Intoarce pointerul catre partea intreaga char* intoarce_zecimal() { return zecimal; } // Intoarce pointerul catre partea zecimala // Atribuire de valori pentru datele private void atribuie_intreg(const char *sir); void atribuie_zecimal(const char *sir); // DE FACUT: Definitii supraincarcare: // - operator +=, -=, *=, /=};// Constructor fara parametriBigReal::BigReal(){ if(DEBUG) std::cout<<"DEBUG: BigReal::BigReal()"<<std::endl; // Alocare spatiu pentru intreg si zecimal si setare la 0.0 intreg = new char[2]; intreg[0] = '0'; intreg[1] = '\0'; zecimal = new char[2]; zecimal[0] = '0'; zecimal[1] = '\0'; semn = true;}// Constructor cu parametru intBigReal::BigReal(int x){ if(DEBUG) std::cout<<"DEBUG: BigReal::BigReal(int)"<<std::endl; // Partea intreaga intreg = intreg_la_sir(x); // Partea zecimala e 0 zecimal = new char[2]; zecimal[0] = '0'; zecimal[1] = '\0';}// Constructor cu parametru doubleBigReal::BigReal(double x){ if(DEBUG) std::cout<<"DEBUG: BigReal::BigReal(double)"<<std::endl; // Pentru partea intreaga, convertim pe aceasta la sir intreg = intreg_la_sir((int)x); // Pentru partea zecimala folosim functia zecimal = zecimala_la_sir(x);}// Constructorul pentru parametru sir de caractereBigReal::BigReal(const char *sir){ if(DEBUG) std::cout<<"DEBUG: BigReal::BigReal(const char*)"<<std::endl; int i, j, rest = 0; // Parcurgem sirul de caractere pana la "." sau "," for(i = 0; sir[i] && (sir[i] != '.') && (sir[i] != ','); i++) {} // Alocam spatiu (i) pentru partea intreaga si o copiem intreg = new char[i + 1]; for(j = 0; j < i; j++) intreg[j] = sir[j]; intreg[j] = '\0'; // Parcurgem sa vedem cate cifre are partea zecimala for(j = i + 1; sir[j]; j++) rest++; // Copiem partea zecimala zecimal = new char[rest + 1]; for(j = i + 1; j < i + rest + 1; j++) zecimal[j - i - 1] = sir[j]; zecimal[j - i - 1] = '\0';}// Constructorul de copiereBigReal::BigReal(BigReal &ob){ if(DEBUG) std::cout<<"DEBUG: BigReal::BigReal(BigReal&)"<<std::endl; char *ps; int i, j; // Citim partea intreaga si preluam marimea ps = ob.intoarce_intreg(); for(i = 0; ps[i]; i++) {} // Alocam spatiu pentru partea intreaga si copiem din ob intreg = new char[i + 1]; for(j = 0; j < i; j++) intreg[j] = ps[j]; intreg[j] = '\0'; // Citim partea zecimala si preluam marimea ps = ob.intoarce_zecimal(); for(i = 0; ps[i]; i++) {} // Alocam spatiu pentru partea intreaga si copiem din ob zecimal = new char[i + 1]; for(j = 0; j < i; j++) zecimal[j] = ps[j]; zecimal[j] = '\0';}// Supraincarcare operator + pentru adunare BigReal + intBigReal& BigReal::operator + (int x){ if(DEBUG) std::cout<<"DEBUG: BigReal::operator + (int)"<<std::endl; BigReal *tmp = new BigReal(); // Atribuim valorile adunate pointerului pe care il vom returna tmp -> atribuie_intreg(aduna_siruri(this -> intreg, intreg_la_sir(x))); tmp -> atribuie_zecimal(this -> zecimal); return *tmp;}// Supraincarcare operator + pentru adunare BigReal + doubleBigReal& BigReal::operator + (double x){ if(DEBUG) std::cout<<"DEBUG: BigReal::operator + (double)"<<std::endl; BigReal *tmp = new BigReal(); // Atribuim valorile adunate pointerului pe care il vom returna tmp -> atribuie_intreg(aduna_siruri(this -> intreg, intreg_la_sir(x))); tmp -> atribuie_zecimal(aduna_siruri(this -> zecimal, zecimala_la_sir(x))); return *tmp;}// Supraincarcare operator + pentru adunare BigReal + BigRealBigReal& BigReal::operator + (BigReal &ob){ if(DEBUG) std::cout<<"DEBUG: BigReal::operator + (BigReal)"<<std::endl; BigReal *tmp = new BigReal(); // Atribuim valorile adunate pointerului pe care il vom returna tmp -> atribuie_intreg(aduna_siruri(this -> intreg, ob.intoarce_intreg())); tmp -> atribuie_zecimal(aduna_siruri(this -> zecimal, ob.intoarce_zecimal())); return *tmp;}// Supraincarcare operator + pentru adunare BigReal + const char *BigReal& BigReal::operator + (const char *sirx){ if(DEBUG) std::cout<<"DEBUG: BigReal::operator + (const char *)"<<std::endl; BigReal *tmp = new BigReal(); // Copiem sirul din parametru intr-un alt sir pentru ca trebuie sa il modificam int l = 0, k; while(sirx[l++]); char *sir = new char[l]; for(k = 0; k < l - 1; k++) sir[k] = sirx[k]; sir[k] = '\0'; // Obtinem lungimea int i = 0; for(i = 0; sir[i] && sir[i] != '.' && sir[i] != ','; i++) {} // Daca contine "," sau "." if(sir[i] == ',' || sir[i] == '.') tmp -> atribuie_zecimal(&sir[i + 1]); else tmp -> atribuie_zecimal("0"); // Partea ntreaga if(i == 0) tmp -> atribuie_intreg("0"); else { // Un mic truc pentru viteza mai mare, la partea zecimala plecam de unde incepe // Punem NULL unde e virgula (pozitia i) ca sa putem folosi partea intreaga ca sir, direct sir[i] = '\0'; tmp -> atribuie_intreg(sir); } // Atribuim valorile adunate pointerului pe care il vom returna tmp -> atribuie_intreg(aduna_siruri(this -> intreg, tmp -> intoarce_intreg())); tmp -> atribuie_zecimal(aduna_siruri(this -> zecimal, tmp -> intoarce_zecimal())); return *tmp;}// Supraincarcare operator + pentru adunare int + BigRealBigReal& operator + (int x, BigReal &ob){ return ob + x;}// Supraincarcare operator + pentru adunare double + BigRealBigReal& operator + (double x, BigReal &ob){ return ob + x;}// Supraincarcare operator + pentru adunare const char* + BigRealBigReal& operator + (const char *x, BigReal &ob){ return ob + x;}// Supraincarcare operator * pentru BigReal * intBigReal& BigReal::operator * (int x){ if(DEBUG) std::cout<<"DEBUG: BigReal::operator * (int)"<<std::endl; BigReal *tmp = new BigReal(); // Adunam de x ori si partea intreaga si partea zecimala for(int i = 1; i <= x; i++) { tmp -> atribuie_intreg(aduna_siruri(tmp -> intoarce_intreg(), this -> intreg)); tmp -> atribuie_zecimal(aduna_siruri(tmp -> intoarce_zecimal(), this -> zecimal)); } return *tmp;}// Supraincarcare operator * pentru int * BigRealBigReal& operator * (int x, BigReal &ob){ return ob * x;}// DestructorulBigReal::~BigReal(){ if(DEBUG) std::cout<<"DEBUG: BigReal::~BigReal()"<<std::endl; // Eliberare memorie delete[] intreg; delete[] zecimal;}// Conversie manuala a partii zecimale a unui double la sir de caracterechar* BigReal::zecimala_la_sir(double x){ if(DEBUG == 2) std::cout<<"DEBUG: zecimala_la_sir(double)"<<std::endl; double nr; // int cif, contor0 = 0, contor9 = 0, cifre = 0; int lungime_cif = 0, i; char cifrute[19]; char *parte_zecimala; // Partea zecimala a parametrului nr = x - (int)x; // Stupid: scriem in fisier std::fstream f("F:/test.txt", std::ios::out); f<<nr; f.close(); // Citim ca sir din fisier std::fstream g("F:/test.txt", std::ios::in); g>>cifrute; g.close(); // Copiem partea zecimala si o returnam while(cifrute[lungime_cif++]); parte_zecimala = new char[lungime_cif - 2]; for(i = 0; i < lungime_cif - 3; i++) parte_zecimala[i] = cifrute[i + 2]; parte_zecimala[i] = '\0';/* // Parcurgem partea zecimala pana intalnim 000000 while(nr != (double)(int)nr && contor0 <= 6 && contor9 <= 6) { cif = (int)(nr * 10); // Verificam daca suntem la secventa de 000000 sau 999999 if(cif == 0) contor0++; else contor0 = 0; if(cif == 9) contor9++; else contor0 = 9; // Punem cifra in vector si incrementam numarul cifrei cifrute[cifre] = cif + 48; cifre++; nr = double(nr * 10) - (double)(int)(nr * 10); } // Alocam spatiu pentru partea zecimala parte_zecimala = new char[cifre - 6]; // Copiem cifrele din sirul temporar in partea zecimala for(i = 0; i < cifre - 7; i++) parte_zecimala[i] = cifrute[i]; parte_zecimala[i] = '\0'; // Returnam pointerul*/ return parte_zecimala;}// Conversie manuala de la int la sir de caracterechar* BigReal::intreg_la_sir(int x){ if(DEBUG == 2) std::cout<<"DEBUG: intreg_la_sir(int)"<<std::endl; char sir[11]; // Maxim 10 cifre (+ \0) int i = 0, j; // Daca x == 0 if(x == 0) { // Partea intreaga va fi 0 intreg = new char[2]; intreg[0] = '0'; intreg[1] = '\0'; } // Daca nu, il transformam in sir else { while(x) { sir[i++] = x % 10 + 48; // Codul ASCII al cifrei x = x / 10; } sir[i] = '\0'; // Alocam spatiu pentru intreg intreg = new char[i]; // Copiem din sirul local in sirul "intreg", ordine inversa for(j = 0; j < i; j++) intreg[j] = sir[i - j - 1]; intreg[i] = '\0'; } return intreg;}// Functie pentru setarea valorii intregi a obiectuluivoid BigReal::atribuie_intreg(const char *sir){ if(DEBUG == 2) std::cout<<"DEBUG: atribuie_intreg(const char *)"<<std::endl; int i, j; // Daca e deja alocat, eliberam memoria si o alocam din nou, apoi copiem sirul if(intreg) delete[] intreg; for(i = 0; sir[i] && e_cifra(sir[i]); i++) {} intreg = new char[i + 1]; for(j = 0; j < i; j++) intreg[j] = sir[j]; intreg[j] = '\0';}// Functie pentru setarea valorii zecimale a obiectuluivoid BigReal::atribuie_zecimal(const char *sir){ if(DEBUG == 2) std::cout<<"DEBUG: atribuie_zecimal(const char *)"<<std::endl; int i, j; // Daca e deja alocat, eliberam memoria si o alocam din nou, apoi copiem sirul if(zecimal) delete[] zecimal; for(i = 0; sir[i] && e_cifra(sir[i]); i++) {} zecimal = new char[i + 1]; for(j = 0; j < i; j++) zecimal[j] = sir[j]; zecimal[j] = '\0';}// Functie ce preia ca parametri 2 siruri de caractere, NUMERE si returneaza suma lor ca sirchar* BigReal::aduna_siruri(const char *sir1, const char *sir2){ if(DEBUG == 2) std::cout<<"DEBUG: aduna_siruri(const char *, const char *)"<<std::endl; // Determinam rapid lungimile sirurilor int lun_1 = 0, lun_2 = 0, ultim; while(sir1[lun_1++]); while(sir2[lun_2++]); // Pozitia ultimei cifre ultim = lun_1 > lun_2 ? lun_1 : lun_2; ultim++; // Alocam spatiu pentru noul sir char *suma_s = new char[ultim]; suma_s[(--ultim)--] = '\0'; int transport = 0, i, j; i = lun_1 - 1; j = lun_2 - 1; // Facem adunarea cat timp avem acelasi nr. de cifre int mic = i < j ? i : j; i--; j--; while(mic--) { // Daca suma e 0-9 if(sir1[i] + sir2[j] + transport < 106) { suma_s[ultim--] = sir1[i] + sir2[j] + transport - 48; // Cifra din suma celor 2 cifre transport = 0; } // Daca depaseste 9 else { suma_s[ultim--] = sir1[i] + sir2[j] + transport - 58; // Cifra din suma celor 2 cifre transport = 1; } i--; j--; } i++; j++; // Pentru numar egal de cifre, daca avem sau nu transport if(i == 0 && j == 0) { if(transport) suma_s[0] = '1'; else { // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; return final; } } //Completam cu cifrele numarului cu mai multe cifre if(i) { // Parcurgem sirul ` si nu uitam de transport while(i) { i--; // Daca e 0 if(sir1[i] + transport == 58) { suma_s[ultim--] = sir1[i] + transport - 10; transport = 1; } else { suma_s[ultim--] = sir1[i] + transport; transport = 0; } } // Daca avem transport, pe prima pozitie avem 1 if(transport) suma_s[0] = '1'; else { // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; return final; } } else if(j) { // Parcurgem sirul 2 si nu uitam de transport while(j) { j--; // Daca e 0 if(sir2[j] + transport == 58) { suma_s[ultim--] = sir2[j] + transport - 10; transport = 1; } else { suma_s[ultim--] = sir2[j] + transport; transport = 0; } } // Daca avem transport, pe prima pozitie avem 1 if(transport) suma_s[0] = '1'; else { // Daca nu, cream un nou sir, fara prima cifra (pentru transport) char *final; int k, lungime = lun_1 > lun_2 ? lun_1 : lun_2; final = new char[lungime]; for(k = 1; k < lungime; k++) final[k - 1] = suma_s[k]; final[k - 1] = '\0'; return final; } } // Returnam suma return suma_s;}// Supraincarcare oeprator << pentru afisarestd::ostream& operator << (std::ostream& flux, BigReal& ob){ if(DEBUG == 2) std::cout<<"DEBUG: operator << (std::ostream&, BigReal&)"<<std::endl; // Afisam partea intreaga si partea zecimala flux << ob.intoarce_intreg(); flux << '.'; flux << ob.intoarce_zecimal(); // Returnam fluxu, pentru operatii imbricate return flux;}// Supraincarcare oeprator >> pentru citire (cu ".", "," si filtrare non-cifre)std::istream& operator >> (std::istream& flux, BigReal& ob){ if(DEBUG == 2) std::cout<<"DEBUG: operator >> (std::istream&, BigReal&)"<<std::endl; char sir[1000]; int i; // Atribuim valorile: intreaga si zecimala obiectului ob, dupa citire flux >> sir; for(i = 0; sir[i] && sir[i] != '.' && sir[i] != ','; i++) {} // Daca contine "," sau "." if(sir[i] == ',' || sir[i] == '.') ob.atribuie_zecimal(&sir[i + 1]); else ob.atribuie_zecimal("0"); // Partea ntreaga if(i == 0) ob.atribuie_intreg("0"); else { // Un mic truc pentru viteza mai mare, la partea zecimala plecam de unde incepe // Punem NULL unde e virgula (pozitia i) ca sa putem folosi partea intreaga ca sir, direct sir[i] = '\0'; ob.atribuie_intreg(sir); } // Returnam fluxu, pentru operatii imbricate return flux;}#endif // BIGREAL_H_INCLUDED[/code]Unele bucati de cod sunt jalnice, dar m-am enervat rau cu double-urile si am scris mult cu o ora inainte sa "il prezint". Quote
Paul4games Posted April 13, 2011 Report Posted April 13, 2011 Zilele astea am rezolvat cateva variante de BAC din 2008 iar in varianta 27 am gasit un algoritm care aduna 2 numere citite,vazandul m-am gandit sa il folosesc in functia mea de adunare pentru ca este o metoda mai eficienta.Deci aici este versiunea a doua a functiei mele:[Delphi] Adunare2 - Pastebin.com Quote
Paul4games Posted April 13, 2011 Report Posted April 13, 2011 de ce ai pus stdcall ?A ramas de la prima functie si atunci l-am pus din greseala iar acum am uitat sa il sterg,da oricum nu afecteaza functia cu nimic....btw tu esti aphex ala care s-a retras din scena sau.....? Quote
aphex Posted April 13, 2011 Report Posted April 13, 2011 function Sum(S1:String;S2:String):String;vari,k:Integer;begin if Length(S1)>Length(S2) then Insert(IntToHex (0,Length(S1)-Length(S2)),S2,1) else Insert(IntToHex (0,Length(S2)-Length(S1)),S1,1); WriteLn(S1);WriteLn(S2); k := 0; for i := Length(S1) downto 1 do begin k := StrToInt(S1) + StrToInt(S2) + k; Result := IntToStr(k mod 10) + Result; k := k div 10; end; if k > 0 then Result := IntTostr(k) + Result;end;uite mi-am permis sa iti modific putin functia oricum ai gandit bine felicitari Quote
Paul4games Posted April 13, 2011 Report Posted April 13, 2011 (edited) Mersi,plm sunt la inceput cu programarea(acum invat) si doar acum am realizat ca ruland acel if in interiorul loopului este executat de i ori si asta are un efect negativ asupra performantei,cat despre modul in care egalezi tu numerele trebuie sa il studiez ca citindul nu prea inteleg cum fara nici un loop reusesti sa faci asa ceva.A si de ce afisezi S1/S2? Edited April 13, 2011 by Paul4games Quote
aphex Posted April 13, 2011 Report Posted April 13, 2011 am afisat s1 s2 ptr debug poti sa le stergi cat despre egalarea numerelor folosesc IntToHex care transforma un numar decimal in hexa cu o lungime specificata de cifree.gIntToHex(0,4) = '0000' Quote
Paul4games Posted April 13, 2011 Report Posted April 13, 2011 Ok am inteles,nu am mai avut chef acum sa caut in helpul de la delphi ce face IntToHex dar oricum codul tau fata de al meu e mult mai eficient.Zilele astea vreau sa ma apuc sa fac o astfel de functie pentru scadere dar este un pic mai complicat si mi-a fost cam lene s aimi bat capul cu ea.... Quote
aphex Posted April 13, 2011 Report Posted April 13, 2011 Ok am inteles,nu am mai avut chef acum sa caut in helpul de la delphi ce face IntToHex dar oricum codul tau fata de al meu e mult mai eficient.Zilele astea vreau sa ma apuc sa fac o astfel de functie pentru scadere dar este un pic mai complicat si mi-a fost cam lene s aimi bat capul cu ea....pai cu lenea nu faci nimic Quote
Paul4games Posted April 13, 2011 Report Posted April 13, 2011 (edited) Aphex acum ti-am testat functia iar daca s1 este egal cu s2 atunci cand se executa:k := StrToInt(S1[i]) + StrToInt(S2[i]) + k;da o eroare pentru ca lafor i:= Length(S1) downto 1lui i i se va atribui S2+1,deci va incerca sa acceseze un element care nu exista,ca sa fixezi aceasta problema trebuie doar sa adaugi un alt test la :if Length(S1)>Length(S2) thenInsert(IntToHex (0,Length(S1)-Length(S2)),S2,1)else Insert(IntToHex (0,Length(S2)-Length(S1)),S1,1);ar trebui sa fie asaif Length(S1)>Length(S2) thenInsert(IntToHex (0,Length(S1)-Length(S2)),S2,1)else if Length(S2)>Length(S1) then Insert(IntToHex (0,Length(S2)-Length(S1)),S1,1); Edited April 13, 2011 by Paul4games Quote