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 \cdots 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. Mai multe detalii aici.

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

Îți place conținutul acestui site?

Dacă vrei să mă susții în întreținerea server-ului și în a scrie mai multe articole de calitate pe acest blog, mă poți ajuta printr-o mică donație!

PayPal