33

How do I get what the digits of a number are in C++ without converting it to strings or character arrays?

4
  • Do u want to get number of digits or all the digits in that number in separate variables or integer array? Commented Sep 9, 2009 at 5:45
  • 1
    What do you mean? Do you want to count the number of digits? Do you want to extract the 5th digit from a number? Commented Sep 9, 2009 at 5:46
  • 1
    Number of what type? Is it integer or double? Commented Sep 9, 2009 at 7:24
  • 1
    I wanted a way to get all the individual digits into something like an array. Commented Sep 9, 2009 at 14:22

15 Answers 15

46

The following prints the digits in order of ascending significance (i.e. units, then tens, etc.):

do {
    int digit = n % 10;
    putchar('0' + digit);
    n /= 10;
} while (n > 0);
Sign up to request clarification or add additional context in comments.

6 Comments

if( n == 0 ) no digits are printed.
Do you expect anything when n == 0? I would expect that to be an invalid input thus undefined behavior or an assert.
Not worthy of a downvote. This is an illustration, not production-ready code.
And n == 0 is a valid input, in my view - the answer is a single digit, '0'.
You hardly need printf, BTW. '0' + digit works in ASCII/Unicode. You realize you have simply re-implemented printf %d, right? sprintf %d the original number into a buffer, then reverse the buffer. Put in \n between the digits if you want. Note that sprintf returns the number of characters printed.
|
20

What about floor(log(number))+1?

With n digits and using base b you can express any number up to pow(b,n)-1. So to get the number of digits of a number x in base b you can use the inverse function of exponentiation: base-b logarithm. To deal with non-integer results you can use the floor()+1 trick.

PS: This works for integers, not for numbers with decimals (in that case you should know what's the precision of the type you are using).

5 Comments

After two years, I still don't get why this answer wasn't good as the others.
You can't use ceil(log(x)) instead of floor(log(x))+1 as ceil returns wrong values when log(x) % 1 == 0(e.g. when x = 100 you expect to get 3 (using floor+1) instead of 2 (using just ceil).
@tunnuz: This was no good answer as this gave the number of digits and not the digits of a number as requested.
@Nippey: what's the differente between "number of digits" and "digits of a number"?
Take the number 123321 as example. The number of digits is 6. The digits of this number are 1,2,3,3,2 and 1.
15

Since everybody is chiming in without knowing the question.
Here is my attempt at futility:

#include <iostream>

template<int D> int getDigit(int val)       {return getDigit<D-1>(val/10);}
template<>      int getDigit<1>(int val)    {return val % 10;}

int main()
{
    std::cout << getDigit<5>(1234567) << "\n";
}

5 Comments

Although the runtime complexity is O( sizeof(int)^2 ) when calculating all digits. Hmm.... And how do you know at what digit to start?
Technically the runtime complexity is O(1) because the code will not change for different input values. Note Big O notation is a measure of how runtime scales in relation to input arguments.
It seems like you pretty much got what i was looking for. Thanks.
If I do qDebug() << getDigit<0>(32);, I get: fatal error C1202: recursive type or function dependency context too complex with MSVC2015. I'm assuming the template parameter determines the index of the digit?
@Mitch: The above works for n >= 1 There is no specialization for zero or negative numbers
13

I have seen many answers, but they all forgot to use do {...} while() loop, which is actually the canonical way to solve this problem and handle 0 properly.

My solution is based on this one by Naveen.

int n = 0;
std::cin>>n;

std::deque<int> digits;
n = abs(n);
do {
    digits.push_front( n % 10);
    n /= 10;
} while (n>0);

Comments

8

You want to some thing like this?

 int n = 0;
    std::cin>>n;

    std::deque<int> digits;
    if(n == 0)
    {
        digits.push_front(0);
        return 0;
    }

    n = abs(n);
    while(n > 0)
    {
        digits.push_front( n % 10);
        n = n /10;
    }
    return 0;

2 Comments

I don't exactly understand how this works. Would need to read up on std containers.
Using std containers is a waste here. Wasting CPU resources doing unnecessary heap operations
6

Something like this:

int* GetDigits(int num, int * array, int len) {
  for (int i = 0; i < len && num != 0; i++) {
    array[i] = num % 10;
    num /= 10;
  }
}

The mod 10's will get you the digits. The div 10s will advance the number.

3 Comments

You might not have len - it's better to terminate when num gets to 0.
Good point. Need len to make sure we don't over-run the array. Added a check for num being 0 though.
This can be easily refactored to generate digits for any base. For now it generates digits only for base 10...
4

Integer version is trivial:

int fiGetDigit(const int n, const int k)
{//Get K-th Digit from a Number (zero-based index)
    switch(k)
    {
        case 0:return n%10;
        case 1:return n/10%10;
        case 2:return n/100%10;
        case 3:return n/1000%10;
        case 4:return n/10000%10;
        case 5:return n/100000%10;
        case 6:return n/1000000%10;
        case 7:return n/10000000%10;
        case 8:return n/100000000%10;
        case 9:return n/1000000000%10;
    }
    return 0;
}

Comments

4

simple recursion:

#include <iostream>

// 0-based index pos
int getDigit (const long number, int pos) 
{
    return (pos == 0) ? number % 10 : getDigit (number/10, --pos);
}

int main (void) {
    std::cout << getDigit (1234567, 4) << "\n";    
}

1 Comment

Brilliantly simple and concise
3

Those solutions are all recursive or iterative. Might a more direct approach be a little more efficient?

Left-to-right:

int getDigit(int from, int index)
{
   return (from / (int)pow(10, floor(log10(from)) - index)) % 10;
}

Right-to-left:

int getDigit(int from, int index)
{
   return (from / pow(10, index)) % 10;
}

Comments

1

First digit (least significant) = num % 10, second digit = floor(num/10)%10, 3rd digit = floor(num/100)%10. etc

2 Comments

Nice and general solution. Going through the floating point floor function doesn't make much sense, though. Do take a look at Martin's solution, too!
Well... I wouldn't actually use floor() but I included that in case the OP was using floats or whatever... just to make it explicit. If he's using int's, then no problem, it's not needed.
1

A simple solution would be to use the log 10 of a number. It returns the total digits of the number - 1. It could be fixed by using converting the number to an int.

int(log10(number)) + 1

Comments

0

Use a sequence of mod 10 and div 10 operations (whatever the syntax is in C++) to assign the digits one at a time to other variables.

In pseudocode

lsd = number mod 10
number = number div 10
next lsd = number mod 10
number = number div 10

etc...

painful! ... but no strings or character arrays.

Comments

0

Not as cool as Martin York's answer, but addressing just an arbitrary a problem:

You can print a positive integer greater than zero rather simply with recursion:

#include <stdio.h>
void print(int x)
{
    if (x>0) {
        print(x/10);
        putchar(x%10 + '0');
    }
}

This will print out the least significant digit last.

Comments

0

Years ago, in response to the above questions I would write the following code:

int i2a_old(int n, char *s)
{
    char d,*e=s;//init begin pointer
    do{*e++='0'+n%10;}while(n/=10);//extract digits
    *e--=0;//set end of str_number
    int digits=e-s;//calc number of digits
    while(s<e)d=*s,*s++=*e,*e--=d;//reverse digits of the number
    return digits;//return number of digits
}

I think that the function printf(...) does something like that.

Now I will write this:

int i2a_new(int n, char *s)
{
    int digits=n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10;
    char *e=&s[digits];//init end pointer
    *e=0;//set end of str_number
    do{*--e='0'+n%10;}while(n/=10);//extract digits
    return digits;//return number of digits
}

Advantages: lookup table indipendent; C,C++,Java,JavaScript,PHP compatible; get number of digits, min comparisons: 3; get number of digits, max comparisons: 4; fast code; a comparison is very simple and fast: cmp reg, immediate_data --> 1 CPU clock.

1 Comment

Your code is broken. It accepts negative numbers but doesn't work with them, and makes assumptions about the size of int
0

Get all the individual digits into something like an array - two variants:

int i2array_BigEndian(int n, char a[11])
{//storing the most significant digit first
    int digits=//obtain the number of digits with 3 or 4 comparisons
    n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10;
    a+=digits;//init end pointer
    do{*--a=n%10;}while(n/=10);//extract digits
    return digits;//return number of digits
}

int i2array_LittleEndian(int n, char a[11])
{//storing the least significant digit first
    char *p=&a[0];//init running pointer
    do{*p++=n%10;}while(n/=10);//extract digits
    return p-a;//return number of digits
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.