Return an unsigned long from vector of ints c++

679 views Asked by At

What's the best method for returning an unsigned long from a vector of ints? I'm working on a BigInt class in c++ and I'm storing the large numbers in a vector. I want to write a method that will return this vector as a standard long, provided it isn't larger than unsigned long can hold. Thanks

1

There are 1 answers

3
Steve Jessop On BEST ANSWER

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 */