Sunteți pe pagina 1din 4

Numere mari

n continuare vom prezenta cum se pot realiza operaii pe numere mari (eng. huge numbers) cu foarte puine linii de cod. n general, muli programatori se complic la aceste operaii, dei nu este nevoie! Vom considera c numerele mari sunt vectori n care elementul de indice 0 indic lungimea numrului, iar cifrele sunt reinute n ordinea invers dect cea a citirii (reprezentarea n oglind).

1. Reprezentarea numerelor mari n memorie a) Reprezentarea sub form de vector


Numere naturale Pentru un numr natural n vom pstra ntr-un vector a irul cifrelor numrului n ncepnd cu cifra unitilor memorat n elementul a[1]. Numrul de cifre al lui n se memoreaz n elementul a[0]. De exemplu, 0 are o singur cifr, deci a[0]=1 i a[1]=0. Variabilele necesare pot fi declarate astfel: 1. long n, a[10001]; Numere ntregi Vom memora semnul pentru numerele ntregi negative Exemple: n n=0 Cifrele lui n (n ordine invers) 0
a

Vectorul a
[0][1][2][3][4][5][6][7][8][9][10] 1 0

n=275

572
a

[0][1][2][3][4][5][6][7][8][9][10] 3 5 7 2

n=1234567890

0987654321

[0][1][2][3][4][5][6][7][8][9][10] a 10 0 9 8 7 6 5 4 3 2 1

b) Iniializarea unui numr mare


Funcia de iniializare poate fi scris sub forma: 1. void init(long n,int a[]) 2. { int i=1; 3. a[0]=1;//o cifra 4. if(n==0) a[1]=0;//cu valoarea 0 5. else 6. { while(n>0) 7. { a[i]=n%10; //a[i] ia valoarea ultimei cifre a lui n 8. n=n/10; //eliminam ultima cifra a numarului n 9. i++; } //trecem la urmatoarea cifra 10. a[0]=i-1; } //actualizam numarul de cifre in a[0] 11. }

c) Copierea (atribuirea) unui numr mare


1. 2. 3. 4. 5. 6. 7. void copiere(long a[], long b[]) //copiem numrul mare b n numrul mare a //efectul este cel al atribuirii a=b { int i; for(i=0;i<=b[0];i++) a[i]=b[i]; }

d) Afiarea unui numr mare


1. void tipar(int a[]) 2. { 3. int i; 4. for(i=a[0];i>=1;i--) 5. cout<<a[i]; 6. cout<<'\n'; 7. }

2. Operaii cu numere mari a) Suma a dou numere mari


1. 2. 3. 4. 5. 6. 7. 8. 9. 10. void adunare(long a[], long b[],long c[]) { int i,t=0; for (i=1; i<=a[0] || i<=b[0] || t; i++) { t=a[i]+b[i]+t; c[i]=t%10; t=t/10; } c[0] = i - 1; // numrul de cifre al lui c }

Varianta condensat (cu mai puine linii de cod)


1. 2. 3. 4. 5. 6. 7. void add(long a[], long b[],long c[]) { int i,t=0; for (i=1; i<=a[0] || i<=b[0] || t; i++,t=t/10) c[i]=(t+=a[i]+b[i])%10; c[0] = i - 1; // numrul de cifre al lui c }

b) Scderea a dou numere mari


1. 2. 3. 4. 5. 6. 7. 8. 9. void sub(int A[], int B[]) { int i, t = 0; for (i = 1; i <= A[0]; i++) { A[i] -= ((i <= B[0]) ? B[i] : 0) + t; A[i] += (t = A[i] < 0) * 10; } for (; A[0] > 1 && !A[A[0]]; A[0]--); }

c) nmulirea unui numr mare cu un numr mic (scalar)


1. 2. 3. 4. 5. 6. 7. void mul(int A[], int B) { int i, t = 0; for (i = 1; i <= A[0] || t; i++, t /= 10) A[i] = (t += A[i] * B) % 10; A[0] = i - 1; }

d) nmulirea unui numr mare cu un numr mare


1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. void mul(int A[], int B[]) { int i, j, t, C[NR_CIFRE]; memset(C, 0, sizeof(C)); for (i = 1; i <= A[0]; i++) { for (t=0, j=1; j <= B[0] || t; j++, t/=10) C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10; if (i + j - 2 > C[0]) C[0] = i + j - 2; } memcpy(A, C, sizeof(C)); }

e) mprirea unui numr mare la un numar mic


1. 2. 3. 4. 5. 6. 7. void div(int A[], int B) { int i, t = 0; for (i = A[0]; i > 0; i--, t %= B) A[i] = (t = t * 10 + A[i]) / B; for (; A[0] > 1 && !A[A[0]]; A[0]--); }

f) Restul unui numr mare mprit la un numr mic


1. 2. 3. 4. 5. 6. 7. int mod(int A[], int B) { int i, t = 0; for (i = A[0]; i > 0; i--) t = (t * 10 + A[i]) % B; return t; }

Aplicaii
1.
Scriei funciile necesare pentru a calcula valoarea an, pentru valori ale lui a i n care verific relaiile: 1 a 106 i 0 n 1000. Valorile lui a i n se citesc din fiierul putere.in i vor fi scrise n putere.out. Calculai termenul de rang n din irul lui Fibonacci, pentru valorile lui n 0 n 1000. Numrul n se va citi din fiierul fibonacci.in iar rezultatul va fi scris n fibonacci.out. irul lui Fibonacci este definit astfel:

2.

F0=0, F1=1, Fn=Fn-1+Fn-2, n 2

3.

Din fiierul numere.in se citesc mai multe numere ntregi cu cel mult 1000 de cifre fiecare. Scriei n fiierul numere.out suma acestor numere.

4.

Determinai ptratul numrului format din n uniti. Numrul n se va citi din fiierul unu.in, iar rezultatul se va trece n fiierul unu.out. Exemplu: patrat.in 3 8 patrat.out 12321 Explicaii 1112=12321
2

123456787654321 11111111 =123456787654321

5.

Se d numrul natural n. S se determine un multiplu al numrului n care are doar cifrele 1 i 0. Numrul n se citete de pe prima linie a fiierului multiplu.in, iar fiierul multiplu.out conine rezultatul cerut. Exemplu: multiplu.in 7 multiplu.out

1111110

6.

Se d numrul natural n i o cifr c. S se determine un multiplu al numrului n care are doar cifrele c i 0. Numrul n se citete de pe prima linie a fiierului cifre.in, iar fiierul cifre.out conine rezultatul cerut. Exemplu: cifre.in 75 cifre.out

50505