How do you combine different numbers into one number ? E.g (1,2,2) = 122



Example : 

    1230304  (B)

1)  0000000  (2)
2)  1000000  (3)
3)  1100000  (3)
4)  1200000  (4)
5)  1210000  (4)
6)  1220000  (4)
7)  1230000  (5)  
8)  1231000  (4)
9)  1230100  (5)
10) 1230200  (5)
11) 1230300  (6)
12) 1230310  (5)
13) 1230301  (6)
14) 1230302  (6)
15) 1230303  (6)
16) 1230304  (7)






Last edited on
That code doesn't compile, would you mind showing the real code? And what is the "possibilities" variable for? It almost makes it sound like you're doing combinatoric math.

And also show the code that you're testing the speed of so that we can try it ourselves?

One micro-optimization would be to remove the std::pow(10, i) calls by just multiplying "code" by 10 each time in the loop, but I'm not sure if that will really make a noticeable improvement.

Last, what is the use-case we're talking about here? What should the result be if the user wants a base-60 number?
Last edited on
@Ganado thank you for your comment


This Is what I have and I made a main to test it

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <cmath>
#include <string>



void Convert_to_base(std::vector<int>&set , int base, int length);

int main(){

  std::vector<int> set;
  Convert_to_base(set, 4, 6);

  for( int i = 0; i< 1296; i++){
      std::cout << set[i] << std::endl;
  }


  return 0;
}


void Convert_to_base(std::vector<int>&set , int base, int length){

    int possibilities = std::pow(base, length);
    std::vector <int> tmp;


    for( int i = 0; i< possibilities; i++){
            int code = 0;
            int remainder = 0;

            do{

                remainder = i % base;
                i = i/base ;
                //
                // here I am trying to sort of "join up" all the remainders here
                //
                tmp.push_back(remainder);

            }while( i =! 0);

            for( int i = 0 ; i< tmp.size(); i++){
                int multiple  = std::pow(10, i);
                code = code + (tmp[i]* multiple) ;
            }

            set.push_back(code);
    }
}




The reason I am doing this is because:

Say you are told to find all the possible numbers you can get given how many numbers are in it and how many number there could be for example.


Say we want a 3 digit number and you can have only 3 numbers (0,1,2)

Then the possibilities would be
000
001
002
010
011
012

....
222


If you are aware of any other methods To do this I would love to see what you think.


In regards, to the bases, the largest base I would need to go up to is 15.
Last edited on
Your code isn't just slow, it takes literally forever :)

I assumed it was a typo in your first post so I didn't mention it: Look at line 45.
} while ( i =! 0);

This is doing:
1. assign i the value of "!0" (which is 1)
2. Loop if the result of this assignment is not 0 (which will always be true)

You meant to do:
while (i != 0);

But wait, there's more!
Your second issue is with your temp vector. You need to clear it every time, or you should declare it within the for loop.

And last, notice that you have a for loop inside a for loop. Both of these for loops, AND the while loop are using the "i" variable. At the end of your while loop, i == 0, and you never advance in your program.

Here's a quick fix, could be optimized more:
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
void Convert_to_base(std::vector<int>&set , int base, int length){

    int possibilities = std::pow(base, length);
    std::vector <int> tmp;

    for( int i = 0; i < possibilities; i++){
        
        int code = 0;

        int temp_num = i;
        do{
            int remainder = temp_num % base;
            temp_num = temp_num/base ;
            //
            // here I am trying to sort of "join up" all the remainders here
            //
            tmp.push_back(remainder);

        }while( temp_num != 0);

        for( int j = 0; j < tmp.size(); j++){
            int multiple  = std::pow(10, j);
            code = code + (tmp[j]* multiple) ;
        }

        set.push_back(code);
        tmp.clear();
    }
}


Hints (possible improvements that I didn't do):
- You should be able to do the inner part with just one while loop instead of your while loop + inner for loop, removing the tmp vector.
- I mentioend this previously, but you can multiply the code by 10 each time instead of doing std::pow(10, j). Might need to change the loop order around to get this to work.
1
2
3
4
        for( size_t j = tmp.size(); j > 0; j--){

            code = 10 * code + (tmp[j-1]);
        }


If you want based > 10 to work correctly, you'll need to figure out what you want to do with 11-15. Should they become hexadecimal (A, B, C, D, E, F)?
If so, you'll need to convert your number into a string.
Read: https://stackoverflow.com/questions/5100718/integer-to-hex-string-in-c
Last edited on
I am going to go away and read about this and come back with more questions!

Thank you for the help I appreciate it.
If you look at a number like 120 you regard it typically as base 10. In that case it is a polynom: sum(aix10i) from i = 0 to 3 in this case. This gives you the recipe: n = a2x102 + a1x101 + a0x100 to shift every figure to its position.

For bases > 10 you have to invent new numerals like 10 = A, 11 = B and so on. Or write figures of a number in braces like 3AB = {3}{10}{11}. This said, forget the a. m. polynom, instead concatenate text. Then you could also go for Babylonian math, the used sexagesimal (base 60) numeral system. See https://en.wikipedia.org/wiki/Plimpton_322
The Issue I have this working code thanks to lastchance::

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
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

const string digits = "0123456789ABCDEF";


string toBase( int n, int base, int length )
{
   string result;
   for ( int i = 0; i < length; i++ )
   {
      result = digits[ n % base ] + result;
      n /= base;
   }
   return result;
}


int main()
{
   const int base = 3;
   const int length = 4;

   int mx = 1;
   for ( int p = 0; p < length; p++ ) mx *= base;
   mx--;

   #define SW << setw( 10 ) <<
   cout SW "Base 10" SW "Base " << base << '\n';
   for ( int n = 0; n <= mx; n++ )
   {
      cout SW n SW toBase( n, base, length )<< '\n';
   }
}


It works great when I compile it but I don't quite understand it. Albeit it is not configured to store the values like I have done it the base conversion works great and I'm sure I can adjust it to do this. The issue Is

How does the const string digits work here ? and what does digits[n % base] do and how does
it work?

what does n even represent here?
Last edited on
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
#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<string> getAll( const string &letters, int length )
{
   vector<string> result;
   if ( length <= 1 )
   {
      for ( char c : letters ) result.push_back( string( 1, c ) );        // base case
   }
   else
   {
      for ( auto left : getAll( letters, length - 1 ) )                   // recursion
      {  
         for ( char c : letters ) result.push_back( left + c );
      }
   }
   return result;
}

int main()
{
   const string digits = "0123456789ABCDEF";    // Numerals to be used - at least base required
// const int base = 3, length = 4;              // You might prefer to try this first
   const int base = 4, length = 6;

   vector<string> all = getAll( digits.substr( 0, base ), length );

   cout << "Size: " << all.size() << '\n';
   cout << "Press enter for values (WARNING: THERE COULD BE A LOT!)\n";   string a;   getline( cin, a );
   for ( string s : all ) cout << s << '\n';
}
Last edited on
what does n even represent here?

Did you ask the author?
@Ganado


I just ran the code and noticed something. Whenever you get to the last number e.g 33 or 233 or 3333 it somehow jumps up to a number with a nine in it e.g 99.
What you are dealing with is called base conversion.

  • Numbers do not have a “base” (or “radix”).

  • Human readable representations of numbers have a radix (or base).


The radix is the number of symbols you use for digits. Most humans use a radix of TEN, with the arabic digits:

    0 1 2 3 4 5 6 7 8 9


After that, numbers are expressed as a polynomial. For example, the number 123 (base=radix=10) is the polynomial:

    1×102 + 2×101 + 3×100

See the radix in there? (All those tens.)

The place is the power to which we raise the radix. The radix works with negative powers too:

    1×10-1 + 2×10-2 = 0.12


The radix can be anything you want. In computer science, radices of 2, 8, 10, and 16 are most common. The following all equivalent:

    10102 (radix = 2, binary)
    128 (radix = 8, octal)
    1010 (radix = 10, decimal)
    A16 (radix = 16, hexadecimal)

Notice that the radix is always expressed in base 10.

Notice also that these are all the same number, even though they are all written differently.


To the exercise you recounted in your OP explains how to take a number and create a human-readable representation of that number. However, there are two important mistakes which I think have confused you.

The exercise converts the base 10 number “17” into a base 3 number.

The base 10 number is 1×101 + 7×100.

The equivalent base 3 number is 1×32 + 2×31 + 2×30 (or 1223).

You can verify that these are equivalent by doing the math:

    1×101 + 7×100
  = 1×10 + 7×1
  = 10 + 7
  = 17

    1×32 + 2×31 + 2×30
  = 1×9 + 2×3 + 2×1
  = 9 + 6 + 2
  = 17


The method to do it is:
  (1) peel off the least significant digit using a remainder of division with the radix
  (2) reduce the number using integer division with the radix
  (3) repeat until there is nothing left.

Here is your example:

    17 / 3 = 5R2   → 2 is the new least significant digit (1’s place)
    5 / 3 = 1R2   → 2 is the next digit (3’s place)
    1 / 3 = 0R1   → 1 is the final digit (9’s place)

What remains is zero, and we can discount an infinite number of leading zeros from any number. So we are done! The new number is:

    1223


Your mission, should you choose to except it, is to take a number (which does not have a base!) and convert it to a human-readable representation using a given radix (or base).

In C++, to obtain the remainder, use the % operator:

    17 % 3 = 2


In C++, use the / to obtain the integer quotient:

    17 / 3 = 5


By repeating, in this order (take the remainder, then take the integer quotient of division), until your number is reduced to zero.


The only special cases you need to worry about are:
  • negative numbers (which I don’t think your homework requires you to care about)
  • zero (if a number is zero to begin with, you still want to output a “0”).


Input:
  • a number, N
  • the radix (or base), R

Loop termination condition:
  • quit when N == 0

Output:
  • a string


One more thing. In C++, to convert a digit into a character, add '0' to it. So I can represent the number 7 by adding the value of the symbol representing zero.

 
  char c = 7 + '0';


The hard part of this kind of assignment is that you peel the least-significant digits off first, and those appear at the end of the string. Fortunately C++ makes that a pretty easy thing to overcome:

1
2
3
4
  std::string s;
  s = '0' + s;  // s == "0"
  s = '4' + s;  // s == "40"
  s = '9' + s;  // s == "940" 


This should be enough to help you write a function that converts a single number into a single string.

Once you have that function written, then you can move on to manipulating lists of numbers and the like.

Hope this helps.
Last edited on
John,
What code? The code I posted a few posts back does not do that (for me), but perhaps there's some minute difference I'm missing that's causing a logical error. Please post the complete code that is erroneous so I can try it out myself.

But I suggest using lastchance's solution anyway, it's cleaner then what I [may have] fixed (based off of your original code).
Last edited on
@ Duthomhas That is very helpful thank you!
@Ganado, I was referring to the last code you optimised from the one I sent in :


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
void Convert_to_base(std::vector<int>&set , int base, int length){

    int possibilities = std::pow(base, length);
    std::vector <int> tmp;

    for( int i = 0; i < possibilities; i++){
        
        int code = 0;

        int temp_num = i;
        do{
            int remainder = temp_num % base;
            temp_num = temp_num/base ;
            //
            // here I am trying to sort of "join up" all the remainders here
            //
            tmp.push_back(remainder);

        }while( temp_num != 0);

        for( int j = 0; j < tmp.size(); j++){
            int multiple  = std::pow(10, j);
            code = code + (tmp[j]* multiple) ;
        }

        set.push_back(code);
        tmp.clear();
    }
}
@last chance Thank you for your code. I have gone through it and it actually gave me a better understanding of strings than I had before. Thank you.
Yes, and I sadly cannot reproduce your issue. That doesn't mean my code is correct, but please post the complete code that is erroneous so I can try it out myself.

out.exe | grep "9" shows nothing for me!
Last edited on
@ Ganado, That is interesting. I must have been messing up somewhere..

Thanks
Topic archived. No new replies allowed.