33

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

Matt Curtis
  • 23,168
  • 8
  • 60
  • 63
chustar
  • 12,225
  • 24
  • 81
  • 119

15 Answers15

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);
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191
  • 1
    if( n == 0 ) no digits are printed. – xtofl Sep 09 '09 at 08:44
  • Do you expect anything when n == 0? I would expect that to be an invalid input thus undefined behavior or an assert. – Martin York Sep 09 '09 at 10:36
  • 4
    Not worthy of a downvote. This is an illustration, not production-ready code. – Vinay Sajip Sep 09 '09 at 10:37
  • 1
    And n == 0 *is* a valid input, in my view - the answer is a single digit, '0'. – Vinay Sajip Sep 09 '09 at 10:38
  • My previous comment was at @xtolf. I think the code was fine. – Martin York Sep 09 '09 at 15:43
  • 1
    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. – Peter Cordes Dec 05 '09 at 23:33
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).

cruizh
  • 2,839
  • 3
  • 18
  • 20
tunnuz
  • 23,338
  • 31
  • 90
  • 128
  • 2
    After two years, I still don't get why this answer wasn't good as the others. – tunnuz Feb 14 '12 at 04:28
  • 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`). – cruizh Jul 19 '13 at 08:34
  • 5
    @tunnuz: This was no good answer as this gave the number of digits and not the digits of a number as requested. – Nippey Jul 19 '13 at 08:59
  • @Nippey: what's the differente between "number of digits" and "digits of a number"? – tunnuz Jul 22 '13 at 13:50
  • 3
    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`. – Nippey Jul 23 '13 at 11:14
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";
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 1
    Although the runtime complexity is O( sizeof(int)^2 ) when calculating all digits. Hmm.... And how do you know at what digit to start? – xtofl Sep 09 '09 at 08:54
  • 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. – Martin York Sep 09 '09 at 10:32
  • 1
    It seems like you pretty much got what i was looking for. Thanks. – chustar Sep 09 '09 at 14:20
  • 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 May 15 '16 at 08:39
  • @Mitch: The above works for `n >= 1` There is no specialization for zero or negative numbers – Martin York May 15 '16 at 15:33
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);
Community
  • 1
  • 1
P Shved
  • 96,026
  • 17
  • 121
  • 165
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;
Naveen
  • 74,600
  • 47
  • 176
  • 233
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.

Steve Rowe
  • 19,411
  • 9
  • 51
  • 82
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;
}
Ivan Gelov
  • 41
  • 1
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";    
}
user unknown
  • 35,537
  • 11
  • 75
  • 121
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;
}
Mac
  • 31
  • 2
1

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

mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 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! – xtofl Sep 09 '09 at 11:02
  • 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. – mpen Sep 10 '09 at 00:02
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
Deep Panchal
  • 129
  • 1
  • 4
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.

pavium
  • 14,808
  • 4
  • 33
  • 50
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.

Matt Curtis
  • 23,168
  • 8
  • 60
  • 63
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.

  • Your code is broken. It accepts negative numbers but doesn't work with them, and makes assumptions about the size of `int` – LtWorf Nov 04 '14 at 13:49
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
}
Ivan Gelov
  • 41
  • 1