Anexar dígitos a un int sin necesidad de convertir a la cadena?
Pregunta
¿Hay una manera segura de añadir un dígito al final de un entero sin convertirlo en una cadena y sin utilizar stringstreams?
Traté de google la respuesta para esto y la mayoría de las soluciones sugeridas convirtiéndola en una cadena y utilizando stringstreams pero me gustaría mantenerlo como un entero para asegurar la integridad de los datos y evitar la conversión de tipos.
También leí una solución que sugirió que multiplicar el int por 10 y luego añadiendo el dígito, sin embargo, esto podría causar un desbordamiento de enteros.
Es esto seguro para hacerlo o hay un método mejor para hacer esto? Y si hago esto se multiplica por 10 y añadir la solución dígitos, ¿qué precauciones debo tomar?
Solución
Su mejor apuesta es la multiplicación por 10 y adición de valor. Usted podría hacer un cheque ingenuo así:
assert(digit >= 0 && digit < 10);
newValue = (oldValue * 10) + digit;
if (newValue < oldValue)
{
// overflow
}
Otros consejos
Para evitar el desbordamiento:
if ((0 <= value) && (value <= ((MAX_INT - 9) / 10))) {
return (value * 10) + digit;
}
En lugar de MAX_INT, se puede usar std::numeric_limits<typeof(value)>::max()
o similar, para soportar tipos distintos de 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)
Esta es una aplicación mejor y más a prueba de balas que el que fue aceptado como una respuesta que también es rápido:
#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);
}
También debe ser capaz de hacer esto en una función en línea. La comprobación de desbordamiento casi siempre cortocircuito después de la primera comparación. La cláusula después de la &&
es simplemente para que pueda (en el caso de una broca 32, de dos entero de complemento) añadir 5 hasta el final de 429.496.729, pero no 6.