Append digit to an int without converting to string?
Solution 1
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
}
Solution 2
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.
Solution 3
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)
Solution 4
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.
nmuntz
Updated on June 23, 2022Comments
-
nmuntz almost 2 years
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? -
Steve Jessop almost 15 yearsThe overflow check is wrong. For example, 4772185889 - 2^32 = 477218593, which is greater than 477218588.
-
Sam almost 15 yearsI agree, I linked to where you can get a less than naive implementation.
-
Omnifarious about 14 yearsI put in an answer later that has a very fast overflow check that always works.