-3

Possible Duplicate:
c++ template for conversion between decimal and arbitrary base

I would like to convert an instance of unsigned int to an instance of std::vector<unsigned int> in base X where X is any number from 2 to maximum number an unsigned int can represent.

EDIT: I used to say an unsigned int in base 10, but that got critical comments, and I think that's right, so I removed it to avoid confusion.

There are a lot of questions and answers on SO that cover something like itoa that converts up to base 16 or 32 or some small number (with this itoa implementation page being pointed out as good resource). I wasn't able to find a nice conversion for bases much larger than that.

Note: Performance is not a concern (within reason).

Community
  • 1
  • 1
Alan Turing
  • 12,223
  • 16
  • 74
  • 116
  • 1
    What exactly do you mean by “an instance of `unsigned int` in base 10”? `unsigned int`s are usually stored in base 2. – Konrad Rudolph Jan 29 '13 at 14:29
  • [What have you tried](http://whathaveyoutried.com)? – Robᵩ Jan 29 '13 at 14:29
  • Why don't you write it yourself? There's no standard way to do it. – Bartek Banachewicz Jan 29 '13 at 14:31
  • 3
    "an instance of `unsigned int` in base 10" does not make any sense. The radix is a property of the *representation* of the number, not of the number itself. – NPE Jan 29 '13 at 14:33
  • @OliCharlesworth You mean on the right ;) – leemes Jan 29 '13 at 14:33
  • It's a simple algorithm that I would normally quickly write myself, and if no one answered, I would write it myself for an answer. I was just hoping that there was a nice STL solution that would lend itself to operations on such vector representations. – Alan Turing Jan 29 '13 at 14:33
  • @OilCharlesworth No that's limited to base 16 or lower like most of the other answers. – Alan Turing Jan 29 '13 at 14:34
  • @LexFridman: Is it? I don't see any limit in the accepted answer. – Oliver Charlesworth Jan 29 '13 at 14:35
  • @KonradRudolph `uint` is stored as binary, but usually they are assigned as decimals, e.g.: `unsigned int x = 37;` – Alan Turing Jan 29 '13 at 14:36
  • @OliCharlesworth Yes, see how `alphabet` in that answer goes from 0 to I? I (aka 19) is the largest base. – Alan Turing Jan 29 '13 at 14:38
  • 1
    @LexFridman: Sure, and you can trivially extend that, or modify it to just write the integer values of each digit. – Oliver Charlesworth Jan 29 '13 at 14:38
  • @Lex That’s irrelevant for the algorithm. – Konrad Rudolph Jan 29 '13 at 14:39
  • @OliCharlesworth The extension is not trivial in the implementation (see answer). The extension IS trivial in the pseudocode. We are not talking about pseudocode, but actually C++ implementation. – Alan Turing Jan 29 '13 at 14:42
  • @LexFridman: All of the answers below are essentially identical to the accepted answer in the linked question... – Oliver Charlesworth Jan 29 '13 at 14:44
  • @OliCharlesworth, and the `char *` and `std::string` implementation of `itoa` are "essentially" the same [on this page](http://www.jb.man.ac.uk/~slowe/cpp/itoa.html) but both are valuable and are presented separately for good reason. – Alan Turing Jan 29 '13 at 14:47
  • @LexFridman: I think you're arguing for no good reason. There's an existing question with the algorithm you're after, and it should be trivial to adapt it to your needs (vector, string, char *, arbitrary base, whatever). If there's something wrong with that solution, you should edit your question to explain the problem. – Oliver Charlesworth Jan 29 '13 at 14:50
  • @OliCharlesworth Let's agree to disagree. Perhaps you are right in terms of the SO community, but I thought that an STL version of this algorithm has a different implementation and it would be useful for someone searching for such a solution. The fact that both the answers so far are slightly incorrect (`push_front` is not a valid function for `vector` and with `push_back` you have to reverse the `vector`) tells me that the extension is not so trivial. – Alan Turing Jan 29 '13 at 15:00

3 Answers3

1

This should do it.

std::vector<unsigned int> result;
unsigned int base = ...;
unsigned int input = ...;
while(input) {
  result.push_back(input%base);
  input /= base;
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • if you `push_back` you have to reverse the `result` vector. – Alan Turing Jan 29 '13 at 14:48
  • 1
    I disagree. If you `push_back()`, then `result[0]` is the ones column, `result[1]` is the 10's column, `result[2]` is the 100's column, etc (assuming base 10, for example). This strikes me as the natural ordering of the vector. – Robᵩ Jan 29 '13 at 15:12
  • a decimal like 4 should produce a vector `{1,0,0}` not `{0,0,1}` in base 2. – Alan Turing Jan 29 '13 at 15:16
  • If you want a reverse answer, then you'll need to apply `std::reverse`. No big deal. – Robᵩ Jan 29 '13 at 15:26
  • Ps. If bigendian storage is a requirement for you, please mention that in the question. – Robᵩ Jan 29 '13 at 15:31
0
std::vector<unsigned int> toBaseX(unsigned int number, unsigned int base)
{
    std::vector<unsigned int> res;

    if (number == 0)
    {
        res.push_back(0);
        return res;
    }

    while (number > 0)
    {
        unsigned int currentDigit = number % base;
        res.push_back(currentDigit);
        number /= base;
    }
    return res;
}
Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94
0

The following code converts x to a vector in base base. It also pad the resulting vector with extra zeros if needed to satisfy minSize size of the resulting vector.

vector<unsigned int> intToAnyBase(unsigned int x, int base, int minSize = 1) {
    assert(base >= 2);

    // minSize allows us to pad the resulting vector
    // with extra zeros at the front if needed
    minSize = std::max(1, minSize);

    std::vector<unsigned int> v;
    while(x > 0) {
        res.push_back(x % base);
        x /= base;
    }

    // Append zeros to the "front" to satisfy 'minSize' requirement.
    // This also adds support for x
    if(v.size() < minSize) {
        v.reserve(minSize);
        while(v.size() < minSize)
            v.push_back(0);
    }

    std::reverse(v.begin(), v.end());

    return v;
}

Note that the resulting vector is reversed in the function so that that, for example, decimal 4 produces {1,0,0} as a result and not {0,0,1}.

Alan Turing
  • 12,223
  • 16
  • 74
  • 116