Problemele cu cifrele unui număr natural sunt printre primele teme abordate la începutul studiului informaticii la școală. Deși par aproape inutile, problemele cu cifrele unui număr au rolul de a te obișnui cu împărțirea întreagă (ce presupune obținerea unui cât și a unui rest) și cu reprezentarea numerelor în baza $10$. Soluțiile sunt foarte scurte, așa că sper că nu e nevoie să scriu programele complete, ci doar secvențele de cod importante.
Problema 1.
Se dă un număr natural $n$. Să se afișeze ultima sa cifră.
Cam la asta se reduc majoritatea problemelor cu cifrele unui număr. Un număr natural de forma $\overline{a_0 a_1 \ldots a_{m - 1}}$ este egal cu $a_0 \cdot 10^{m - 1} + a_1 \cdot 10^{m - 2} + \cdots + a_{m - 1} \cdot 10^0$. Observăm că, din această sumă, doar ultimul termen (care reprezintă ultima cifră) nu este un multiplu nenul de $10$, așa că prin împărțirea numărului la $10$, restul obținut va fi chiar ultima sa cifră.
int lastDigit = n % 10;
Problema 2.
Se dă un număr natural $n$. Să se afișeze numărul format prim eliminarea ultimei sale cifre.
Ne vom folosi din nou de forma unui număr natural scris în baza $10$, din care se deduce că împărțirea lui $n$ la $10$ va produce câtul $a_0 \cdot 10^{m - 2} + a_1 \cdot 10^{m - 3} + \cdots + a_{m - 2} \cdot 10^0$. Fiecare termen devine de $10$ ori mai mic, iar ultimul dispare, numărul obținut find practic cel cerut.
int lastDigitCut = n / 10;
Problema 3.
Se dă un număr natural $n$. Să se afișeze numărul format din ultimele $k$ cifre ale lui $n$.
Vom generaliza problema 1. Restul împărțirii lui $n$ la $10$ este ultima sa cifră, restul împărțirii lui $n$ la $100$ este numărul format din ultimele sale două cifre etc. Așadar, trebuie să calculăm restul împărțirii lui $n$ la $10^k$.
int p = 1;
for (int i = 0; i < k; i++)
p *= 10;
cout << n % p << '\n';
Problema 4.
Se dă un număr natural $n$. Să se afișeze numărul format prin eliminarea ultimelor $k$ cifre ale lui $n$.
Procedăm ca la problema 2. Dacă restul împărțirii lui $n$ la $10^k$ este numărul format din ultimele $k$ cifre, atunci câtul împărțirii este numărul format prin eliminarea acelor cifre.
int p = 1;
for (int i = 0; i < k; i++)
p *= 10;
cout << n / p << '\n';
Problema 5.
Se dă un număr natural $n$. Să se afișeze a $k$-a cifră a sa, considerându-le numerotate de la $1$, de la stânga la dreapta.
Folosind ce am învățat până acum, putem calcula numărul format din primele $k$ cifre (prin eliminarea ultimelor $m - k$). Din acesta avem nevoie doar de ultima cifră, deci îi calculăm restul împărțirii la $10$.
int p = 1;
for (int i = 0; i < m - k; i++)
p *= 10;
cout << n / p % 10 << '\n';
Problema 6.
Se dă un număr natural $n$. Să se calculeze numărul lui de cifre.
Soluția este să împărțim numărul la $10$ până când acesta devine $0$, iar la fiecare pas să incrementăm numărul de cifre. De exemplu, la pasul $0$ avem numărul $618$, la pasul $1$ avem $61$, la pasul $2$ avem $6$, la pasul $3$ avem $0$, iar aici ne oprim. Numărul de cifre ale lui $618$ este $3$. Vom trata separat cazul $n = 0$, pentru că dacă numărul este $0$ din start, nu s-ar mai intra în while
.
int nrDigits = 0;
if (!n)
nrDigits = 1;
// Nu are rost să punem else pentru că oricum
// dacă n == 0 nu se intră în while.
while (n) {
nrDigits++;
n /= 10;
}
cout << nrDigits << '\n';
Totuși, if
-ul ăla este cam enervant. Îl putem evita folosind structura do while
:
int nrDigits = 0;
do {
nrDigits++;
n /= 10;
} while (n);
cout << nrDigits << '\n';
Dacă $n \neq 0$, do while
-ul va face exact aceeași pași ca while
-ul de la început, singura diferență fiind momentul la care se testează condiția. Dacă $n = 0$, se incrementează numărul de cifre, $n$ se împarte la $10$, obținând tot $0$, și se iese din do while
. Rezultatul va fi așadar $1$, ceea ce este corect.
Se observă că, la final, în $n$ nu vom mai avea stocată valoarea inițială a numărului, ci $0$. Dacă avem nevoie de aceasta și după calcularea numărului de cifre, îi putem face la început o copie în variabila $cpy$, și să o prelucrăm în schimb pe aceasta.
int cpy = n;
int nrDigits = 0;
do {
nrDigits++;
cpy /= 10;
} while (cpy);
cout << nrDigits << '\n';
Problema 7.
Se dă un număr natural $n$. Să se calculeze suma cifrelor acestuia.
În multe probleme cu cifrele unui număr se folosește șablonul de la problema anterioară. Înainte de eliminarea ultimei cifre de la fiecare pas, o putem prelucra accesând-o prin n % 10
. În cazul nostru, prelucrarea înseamnă să o adăugăm la sumă.
int sum = 0;
while (n) {
sum += n % 10;
n /= 10;
}
cout << sum << '\n';
Problema 8.
Se dă un număr natural $n$. Să se afișeze cifra sa maximă.
Din nou, eliminăm pe rând ultima cifră a lui $n$ până când acesta devine $0$, iar la fiecare pas actualizăm maximul.
int max = 0;
while (n) {
if (n % 10 > max)
max = n % 10;
n /= 10;
}
cout << max << '\n';
Problema 9.
Se dă un număr natural $n$. Să se determine prima sa cifră (cea mai semnificativă cifră).
Putem extrage câte o cifră din $n$ până când $n$ devine mai mic decât $10$, adică până când $n$ devine o cifră. Aceasta va fi, evident, ultima cifră a lui $n$.
while (n > 9)
n /= 10;
cout << n << '\n';
Problema 10.
Se dau $k$ cifre. Să se construiască numărul natural $n$ format din aceste cifre în ordinea în care sunt date.
La fiecare cifră citită îl vom înmulți pe $n$ cu $10$, pentru a-i face loc cifrei curente, $x$. După înmulțire, $n$ va avea un $0$ la final, iar adunând $x$, $0$-ul va deveni $x$.
int k; cin >> k;
int n = 0;
for (int i = 0; i < k; i++) {
int x; cin >> x;
n = n * 10 + x;
}
cout << n << '\n';
Problema 11.
Se dau $k$ cifre. Să se construiască numărul natural $n$ format din aceste cifre în ordinea inversă celei în care sunt date.
Procedăm aproape ca la problema anterioară, numai că vom reține pe parcurs și o putere a lui $10$ ($10^i$). La fiecare pas vom înmulți cifra curentă $x$ cu această putere, adăugând la finalul său $i$ zerouri ($i$ fiind egal și cu numărul de cifre ale lui $n$ la pasul respectiv). Astfel, putem adăuga $n$-ul vechi la acest număr, formând un nou $n$.
int k; cin >> k;
int n = 0;
for (int i = 0, p = 1; i < k; i++, p *= 10) {
int x; cin >> x;
n = x * p + n;
}
cout << n << '\n';
Problema 12.
Se dă un număr natural $n$. Să se calculeze răsturnatul (oglinditul) său. Răsturnatul unui număr este numărul format prin scrierea în ordine inversă a cifrelor sale. De exemplu, răsturnatul lui $618$ este $816$.
Aici vom combina problemele 7 și 10. Pe măsură ce eliminăm câte o cifră din $n$, o adăugăm la răsturnatul lui $n$, pe care îl vom nota cu $m$.
int m = 0;
while (n) {
m = m * 10 + n % 10;
n /= 10;
}
cout << m << '\n';
Problema 13.
Se dă un număr natural $n$. Să se determine dacă $n$ este un palindrom. Un număr palindrom este un număr care citit atât de la dreapta la stânga, cât și de la stânga la dreapta, este același.
Cu alte cuvinte, $n$ este palindrom dacă $n$ este egal cu răsturnatul său. Vom reține o copie a lui $n$ pe care o vom prelucra pentru a obține răsturnatul ($m$). Apoi, testăm egalitatea dintre $n$ și $m$.
int m = 0;
int cpy = n;
while (cpy) {
m = m * 10 + cpy % 10;
cpy /= 10;
}
if (n == m)
cout << "DA\n";
else
cout << "NU\n";
Problema 14.
Se dă un număr natural $n$. Să se determine cifra de control a lui $n$. Cifra de control a unui număr este cifra de control a sumei cifrelor sale, dacă numărul are măcar două cifre. Altfel, este chiar numărul în sine.
Cam așa sună o definiție recursivă a cifrei de control. Altfel spus, cât timp $n$ nu este o cifră, $n$ devine suma cifrelor lui $n$. La final, răspunsul va fi $n$.
int sum;
while (n > 9) {
sum = 0;
while (n) {
sum += n % 10;
n /= 10;
}
n = sum;
}
cout << n << '\n';
Dar putem găsi o soluție ceva mai eficientă. Se poate observa că dacă $n$ are cifra de control $c$, atunci toate numerele naturale de forma $n + 9k$, cu $k$ întreg, au și ele cifra de control $c$. Asta înseamnă că cifra de control a lui $n$ este restul împărțirii sumei cifrelor sale la $9$ dacă restul este nenul, sau $9$ în caz contrar.
int sum = 0;
while (n) {
sum += n % 10;
n /= 10;
}
if (sum % 9)
cout << sum % 9 << '\n';
else
cout << "9\n";
Acestea sunt cele mai clasice exerciții cu cifrele unui număr; important este să rețineți cum se extrag cifrele dintr-un număr. Puteți exersa astfel de probleme pe PbInfo; acolo se găsesc și o parte din cele prezentate în acest articol. Dacă aveți vreo problemă legată de cifrele unui număr care vă dă bătăi de cap, nu ezitați să o lăsați într-un comentariu mai jos, pentru a vă ajuta