Something along these lines, assuming the ints are stored in the vector with the least significant first:
size_t bits_in_int = std::numeric_limits<int>::digits;
size_t bits_in_ulong = std::numeric_limits<unsigned long>::digits;
unsigned long accumulator = 0;
size_t bits_so_far = 0;
for (unsigned long i : the_ints) {
size_t next_bits = bits_so_far + bits_in_int;
if (next_bits > bits_in_long) { /* failed, do something about it */}
accumulator += (i << bits_so_far);
bits_so_far = next_bits;
}
return accumulator;
Notes:
1) In practice you could save some bother because the number of loops is going to be either 1 or 2 on any vaguely normal-looking C++ implementation. So you could just write a case where you return the_ints[0]
and a case where you return the_ints[0] + (the_ints[1] << bits_in_int)
.
2) I've been lazy. Because int
is signed and unsigned long
is unsigned, you can actually fit at least one int
plus the least significant bit of another int
into an unsigned long
. For example you might find bits_in_int
is 31 but bits_in_long
is 32.
So actually in the "failed" case there is one last hope for peace, which is that (a) there is only one int
left to process, and (b) its value fits in the remaining bits of the result. But like I say, I'm lazy, and I think I've shown the components you need to put together.
For this reason if no other, you should probably use a vector of unsigned int
for your BigInt. It's not required that the width of unsigned long
is a multiple of the number of bits in unsigned int
, but it might be strange enough that you can ignore it.
Update for base 10 digits, stored most significant first:
if (the_ints.size() <= std::numeric_limits<unsigned long>::digits10 + 1) {
std::stringstream ss;
for (int i : the_ints) ss << char(i + '0');
unsigned long result;
if (ss >> result) return result;
}
/* failed, do something about it */