Seperating an integer number into digits

Pages: 12
Hi everyone,

I have something like:

1
2
int number = 789;
vector<int> myvector;

I would like to separate 789 into its digits and insert them into myvector
in such a way that 7 goes into the first element, 8 into the second element etc.

Thanks in advance.
Yes.
1 Store int number into a string
2 Parse the string into characters (which will be ur digits)
3 Convert each character (ie: digit) into an integer again with stringstream (for example)
4 Store the final digit(s) into myvector
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
int value = 234;
int digits = log10((float)value) + 1; //this determines the number of digits

for (int i = digits - 1; i > 0; i--) {
	int divisor = pow((float)10, i);
	int digit = value / divisor;

	value -= digit * divisor;

	//insert digit into vector
}

//insert last digit into vector 
1
2
3
4
5
6
7
std::vector<int> seperate_into_digits( unsigned int value )
{
    std::vector<int> digits ;
    for( ; value > 0 ; value /= 10 ) digits.push_back( value%10 ) ;
    std::reverse( digits.begin(), digits.end() ) ;
    return digits ;
}
I like ssrun 's way because anyone who uses logarithms is cool :D
Please how do you put the code in the purple field ?
Careless use of floating point, while arguably being cool, is also prone to inaccuracies.

1
2
3
int value = 99999999 ;
int digits = std::log10((float)value) + 1; //this determines the number of digits
std::cout << digits << '\n' ; // prints '9' on my implementation 



EDIT:
> Please how do you put the code in the purple field ?

Select the code and click on the "<>" button on the right.

Or
[code] <your code here> [/code]

Last edited on
JLBorges
How did you do to put your code in the purple field ?
I wanna put my contribution too.
SSRUN
Thank you sir, you saved me a lot of hair tearing out
U'r right JLBorges. U do have the best solution. I just liked the nonstandard approach of logs cuz I wouldn't have thought of it.
If u'r still here coolbran u should implement JLBorges's vector approach. Sorry if I mislead u with my previous comment...

ps: unless of course ssrun can plug those potential 'inaccuracies' hehe XD
Last edited on
Although I suggested something similar to SSRUN's function in another thread, I would have to suggest JLBorge's.
1. It doesn't use log(), which is a decent improvement. (But instead has 2 divisions per cycle, although since integer division is much better on processors these days this isn't too bad)
2. It doesn't rely on FP math for precise results.
3. It has less assignment operations. (But instead uses reverse())
This is the code that (and maybe) soranz suggests

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# include <iostream>
# include <vector>
# include <sstream>
using namespace std;

int get_nbr_digits(int);

int main()
{
    stringstream ss;
    string str;

    int number = 789;
    int dgtNbr = get_nbr_digits(number);

    ss << number;
    ss >> str;

    vector<int>myVector(dgtNbr);
    for(int i=0;i<dgtNbr;i++)myVector[i] = str[i]-'0';

    for(int i=0;i<dgtNbr;i++)
        cout << myVector[i] << endl;
}

int get_nbr_digits(int nbr)
{
    // This function calculates the number of the digits in a number giving
    // which is in this case the parameter nbr
    // PS : If you know the number of the digits you can abandon this function ,
    //      if you get an input this is the right function for the job

    int increase = 0;

    for(int i=0,j=1;i<10;i++,j*=10)// I choose 10 because INT_MAX contain 10 digits
    {
        if((nbr/j)!=0)increase++;
        else break;
    }return increase;
}
@Techno01
You don't need to get the number of digits if you're using a stream:
1
2
3
4
5
6
7
std::stringstream ss;
ss<<234;
char temp;
while(ss>>temp)
{
	std::cout<<int(temp-'0')<<endl;
}
Thanks BlackSheep ,
But I think I mention it in the PS : if am I right !
The function only usefull when we need to input a number

coolbran uses 3 digits in number without inputing it,but what if we input 6 digits in number I do so just to variate the myVector

any observation would be appreciated
> I choose 10 because INT_MAX contain 10 digits

INT_MAX may not be 10 digits long on every implementation.
/* i<10 */ i <= std::numeric_limits<int>::digits10 (#include <limits>)

If there is no compelling reason that a std::vector<> must be used:
1
2
3
4
5
6
std::deque<int> seperate_into_digits( unsigned int value )
{
    std::deque<int> digits ;
    for( ; value > 0 ; value /= 10 ) digits.push_front( value%10 ) ;
    return digits ;
}


Or if we want to take the 'convert to string' path:
1
2
3
4
5
6
std::vector<int> seperate_into_digits2( unsigned int value )
{
    std::string digits = std::to_string(value) ; // C++11
    for( char& c : digits ) c -= '0' ; // C++11
    return std::vector<int>( digits.rbegin(), digits.rend() ) ;
}

Sorry, didn't realize log10 doesn't calculate properly at high values. :(
Anyways, even if it did, JLBorges solution is the preferable one. :P

Cheers everyone!
soranz: > I just liked the nonstandard approach of logs cuz I wouldn't have thought of it.

It is an elegant and mathematically correct algorithm. Lots to like about it.

I just wanted to point out that the intrinsic nature of floating point arithmetic and the numerical approximations in functions like std::log10() gives rise to non-trivial problems in its implementation.


ssrun: > Sorry, didn't realize log10 doesn't calculate properly at high values.

There is absolutely nothing to be apologetic about - it is an elegant algorithm. If the thread made you realize (or reminded you once again) that there are accuracy issues involved, you should be glad.


PS: Hadn't looked at the replies earlier (till a PM made me look at this thread again); hence this late responses.


@JLBorges
1
2
3
4
5
6
7
 std::vector<int> seperate_into_digits( unsigned int value )
{
    std::vector<int> digits ;
    for( ; value > 0 ; value /= 10 ) digits.push_back( value%10 ) ;
    std::reverse( digits.begin(), digits.end() ) ;
    return digits ;
} 



0 is also a number. So more correctly it would be write the function the following way

1
2
3
4
5
6
7
8
9
10
 std::vector<int> seperate_into_digits( unsigned int value )
{
    std::vector<int> digits ;
    do
    {
        digits.push_back( value%10 ) ;
    } while ( value /= 10 );
    std::reverse( digits.begin(), digits.end() ) ;
    return digits ;
} 


It is interesting also to consider a recursive function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <vector>

void split_into_digits( std::vector<unsigned int> &v, unsigned int value )
{
   constexpr unsigned int base = 10;
   unsigned int digit = value % base;
   
   if ( value /= base ) split_into_digits( v, value );
   
   v.push_back( digit );
}


int main()
{
   std::vector<unsigned int> v;
   
   split_into_digits( v, 12345678 );
   
   for ( auto x : v ) std::cout << x << ' ';
   std::cout <<  std::endl;
   
   return 0;
}
> 0 is also a number. So more correctly it would be write the function the following way

You are right. Thanks.


> It is interesting also to consider a recursive function

Yeah, but it doesn't buy much - it is not tail recursion.


I think the best option would be to use a std::deque<> with push_front() (which of course can be made tail recursive).
1
2
@JLBorges
Yeah, but it doesn't buy much - it is not tail recursion. 


I tried to implement a tail recursion with MS VC++ 2010 but I did not find which compiler options must be set that the compiler will generate the code for the tail recursion. So I do not rely upon the tail recursion.
Pages: 12