Append digit to an int without converting to string?
Question
Is there a safe way of adding a digit at the end of an integer without converting it to a string and without using stringstreams ?
I tried to google the answer for this and most solutions suggested converting it to a string and using stringstreams but I would like to keep it as an integer to ensure data integrity and to avoid converting types.
I also read a solution which suggested to multiply the int by 10 and then adding the digit, however this might cause an integer overflow.
Is this safe to do or is there a better method for doing this? And if I do this multiply by 10 and add the digits solution, what precautions should I take?
Solution
Your best bet is the multiplication by 10 and addition of the value. You could do a naive check like so:
assert(digit >= 0 && digit < 10);
newValue = (oldValue * 10) + digit;
if (newValue < oldValue)
{
// overflow
}
OTHER TIPS
To prevent overflow:
if ((0 <= value) && (value <= ((MAX_INT - 9) / 10))) {
return (value * 10) + digit;
}
In place of MAX_INT, you could use std::numeric_limits<typeof(value)>::max()
or similar, to support types other than int.
assert(digit >= 0 && digit < 10); newvalue = 10 * oldvalue; if (oldvalue < 0 ) { newvalue -= digit; } else { newvalue += digit; } // check for overflow SGN(oldvalue) == 0 || SGN(newvalue) == SGN(oldvalue)
Here is a better and more bulletproof implementation than the one that was accepted as an answer that is also fast:
#include <climits>
#include <cassert>
unsigned int add_digit(unsigned int val, unsigned int digit)
{
// These should be computed at compile time and never even be given a memory location
static const unsigned int max_no_overflow = (UINT_MAX - 9) / 10U;
static const unsigned int max_maybe_overflow = UINT_MAX / 10U;
static const unsigned int last_digit = UINT_MAX % 10;
assert(digit >= 0 && digit < 10);
if ((val > max_no_overflow) && ((val > max_maybe_overflow) || (digit > last_digit))) {
// handle overflow
} else {
return val * 10 + digit;
}
assert(false);
}
You should also be able to make this into an inline function. The overflow check will almost always short circuit after the first comparison. The clause after the &&
is simply so you can (in the case of a 32 bit, two's complement integer) add 5 to the end of 429496729, but not 6.