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?

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top