Documente Academic
Documente Profesional
Documente Cultură
Discuție preliminară
1. Operațiile cu numere mari sunt necesare în probleme unde întâlnim numere ce depășesc
limita tipurilor de date oferite de limbajul de programare. În cazul C++, tipul de date cu
limita cea mai mare este “unsigned long long”, ce poate reține numere pana la 264.
2. Pentru a reuși să reținem în memorie numere > 264, vom folosi o altă structură, anume un
vector, unde în fiecare celulă vom reține o cifră a numărului în cauză. În continuare vom
vorbi despre cum să formăm acest vector și despre operațiile ce trebuie implementate
pentru a simula adunarea, înmulțirea etc.
Sunt necesare aceste 2 reguli de formatare a numărului în memorie pentru a ne fi mai ușor să
implementăm operații mai eficiente pe aceste numere.
Citirea
În momentul citirii vom realiza formatarea precizată mai
sus. După ce vom citi numărul de cifre, vom completa
vectorul A de la sfârșit spre început, iar pe poziția 0 vom
reține numărul de cifre din A.
Scrierea
Este asemănătoare cu citirea (se va efectua tot în mod descrescător).
1
Inițializarea și atribuirea
Inițializarea unui număr mare A se face prin declararea unui vector așa cum este menționat și mai
sus. Important este să setăm A{0] = 0, pentru a sugera faptul că în acest număr nu avem nici o
cifră. (atenție: dacă dorim sa avem cifra 0 memorată, atunci A[0]=1, A[1]=0)
Atribuirea se va face diferit, în funcție de valoarea atribuită. Vom vedea și în partea de operații
aritmetice că vom avea în mare parte câte două tipuri de înmulțiri, împărțiri etc.
În cazul în care sunt egale lungimile, atunci vom fi
nevoiți să parcurgem ambele numere mari.
Parcurgerea va fi de la dreapta la stânga și
simultană, adică verificăm numerele cifră cu cifră
pâna când găsim o cifră distinctă.
2
3
1. În cazul înmulțirii cu o 10x, trebuie să mutăm cifrele cu x poziții la dreapta. Vom folosi
memove pentru a muta cifrele și memset pentru a umple spațiul gol cu 0. La numărul de
cifre trebuie sa adăugăm x.
2. În cazul împărțirii prin 10x, trebuie să mutăm cifrele cu x poziții începând de la x+1 la
stânga. Vom folosi de asemenea memove. Nu mai este necesar memset, deoarece este
suficient sa schimbăm A[0] - numărul de cifre.
Deci fiecare cifra din număr va fi înmulțită cu x,
evident existând și un transport ce nu are
doar o cifră. Așadar la final trebuie adăugate
la capăt cifrele transportului. Important!
Transportul va fi mereu mai mic ca x. (suma34)
4
În sfârșit, motivul pentru care la pasul 4 vom avea un rest de o singură cifră de datorează
următoarelor inegalități: 10N-1 <= A < 10N, 10M-1 <= B < 10M, deci 10N+M-2 <= A*B < 10N+M. C va avea ori
N+M-1 cifre (cazul în care nu avem transport la final). Dacă vom avea un transport, atunci acesta
va avea o singură cifră, pentru ca C să aibă N+M cifre. Dacă transportul va avea mai mult de o
cifră, atunci C ar avea mai mult de N+M cifre, ce contrazice inegalitatea de mai sus. Atenție! Este
vorba doar de transportul de la final (după execuția forului), transporturile din interiorul numărului
pot avea mai mult de o cifra. (putereN, SumaGauss1)
5
Se “coboară” cifrele numărului mare pe rând începând cu cifra cea mai semnificativă la sfârșitul
restului actual și se împarte prin scalar. Câtul ce va fi format dintr-o cifră se va adăuga la sfârșitul
numărului, iar restul se va păstra pentru a continua procedeul. Restul de la sfârșitul algoritmului
va reprezenta evident, restul împărțirii.
De asemenea, dacă se dorește doar restul împărțirii numărului mare la scalar, atunci se poate
renunța la liniile de cod legate de cât. Este necesară doar calcularea restului, dar nu și stocarea
unui cât. Restul va fi mereu mai mic ca și x, deci nu trebuie sa ne facem probleme legate de tipul
de date alocat lui r. (numere20)
6
Algoritmul este asemănător cu cel al împărțirii
printr-un scalar, însă în acest caz suntem
obligați să găsim alternative pentru operațiile
de înmulțire cu 10 și împărțire.
1. Din fericire, avem un algoritm scurt de
înmulțire cu 10 explicat mai sus.
2. Împărțirea o vom simula prin scăderi.
În cel mai rău caz vom executa 9
scăderi, deoarece câtul acestei
înmulțiri este o cifră.
În rest, ideea este la fel ca cea de mai sus
(coborârea unei cifre și împărțirea prin B
pentru a obține restul local).
Atenție! Pentru ultimele doua operații menționate, avem nevoie de împărțirea cu un scalar,
pentru a determina mijlocul în căutarea binară.
7
Exerciții de antrenament
Exercițiile sunt preluate parțial din documentația suplimentară. Posibil să existe și rezolvări ce nu
implică numere mari. De asemenea, există unele exerciții cu grad de dificultate mai ridicat.
Recomandarea mea este să se rezolve problemele ce apar pe parcursul lecției, iar apoi cele de la
temă. Sunt necesare pentru exersarea implementărilor ce includ numere mari. După care să se
insiste pe exercițiile suplimentare. Există unele probleme din documentație ce nu sunt incluse aici
1. Campion.edu.ro
a. http://campion.edu.ro/arhiva/index.php?page=problem&action=view&id=1570
b. http://campion.edu.ro/arhiva/index.php?page=problem&action=view&id=1106
c. http://campion.edu.ro/arhiva/index.php?page=problem&action=view&id=438
d. http://campion.edu.ro/arhiva/index.php?page=problem&action=view&id=432
e. http://campion.edu.ro/arhiva/index.php?page=problem&action=view&id=1081
2. Infoarena
a. https://infoarena.ro/problema/biti2
b. https://infoarena.ro/problema/patrate2
c. https://infoarena.ro/problema/aladdin2
d. https://infoarena.ro/problema/next
e. https://infoarena.ro/problema/tort
Temă
1. Factorial1
2. Prim023
3. Stele
8
Update 2019
Probleme noi pentru antrenament
1. {{2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - -}}
9