Jump to content
Nytro

[C++] Suma numere mari

Recommended Posts

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 sir

char* 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.com

Mi-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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 asta

Edit 2 : Gata scuze ti-am corectat numele , ma apuc sa scriu inca o varianta la asta

Edited by Robert1995
Link to comment
Share on other sites

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 by begood
Link to comment
Share on other sites

@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 cod

btw functia mea nu este optimizata,am vrut sa o optimizez acum dar sunt obosit si dupa cateva modificari iara nu mai functiona calumea

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 ulterioare

struct 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 clasei

class 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 parametri

BigReal::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 int

BigReal::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 double

BigReal::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 caractere

BigReal::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 copiere

BigReal::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 + int

BigReal& 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 + double

BigReal& 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 + BigReal

BigReal& 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 + BigReal

BigReal& operator + (int x, BigReal &ob)
{
return ob + x;
}

// Supraincarcare operator + pentru adunare double + BigReal

BigReal& operator + (double x, BigReal &ob)
{
return ob + x;
}

// Supraincarcare operator + pentru adunare const char* + BigReal

BigReal& operator + (const char *x, BigReal &ob)
{
return ob + x;
}

// Supraincarcare operator * pentru BigReal * int

BigReal& 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 * BigReal

BigReal& operator * (int x, BigReal &ob)
{
return ob * x;
}

// Destructorul

BigReal::~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 caractere

char* 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 caractere

char* 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 obiectului

void 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 obiectului

void 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 sir

char* 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 afisare

std::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".

Link to comment
Share on other sites

function Sum(S1:String;S2:String):String;

var

i,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

Link to comment
Share on other sites

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 by Paul4games
Link to comment
Share on other sites

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....

Link to comment
Share on other sites

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 ;)

Link to comment
Share on other sites

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 la


for i:= Length(S1) downto 1

lui 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) then
Insert(IntToHex (0,Length(S1)-Length(S2)),S2,1)
else Insert(IntToHex (0,Length(S2)-Length(S1)),S1,1);

ar trebui sa fie asa


if Length(S1)>Length(S2) then
Insert(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 by Paul4games
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...