Pergunta

Existe uma maneira segura de adicionar um dígito no final de um inteiro sem convertê-lo em uma string e sem usar stringstreams?

Eu tentei google a resposta para este e mais soluções sugeridas convertê-lo para uma string e usando stringstreams mas eu gostaria de mantê-lo como um número inteiro para garantir a integridade dos dados e evitar a conversão de tipos.
Eu também li uma solução que sugeriu para multiplicar o int por 10 e, em seguida, adicionar o dígito, no entanto, isso pode causar um estouro de inteiro.
É seguro fazer ou há um método melhor para fazer isso? E se eu fizer isso multiplicar por 10 e adicione a solução dígitos, que precauções devo tomar?

Foi útil?

Solução

Sua melhor aposta é a multiplicação por 10 e adição de valor. Você poderia fazer a verificação ingênuo assim:

assert(digit >= 0 && digit < 10);
newValue = (oldValue * 10) + digit;
if (newValue < oldValue)
{
    // overflow
}

Outras dicas

Para evitar overflow:

if ((0 <= value) && (value <= ((MAX_INT - 9) / 10))) {
    return (value * 10) + digit;
}

No lugar de MAX_INT, você poderia usar std::numeric_limits<typeof(value)>::max() ou similar, para os tipos de apoio que não seja 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)

Aqui está uma melhor e mais aplicação à prova de balas do que aquele que foi aceito como uma resposta que também é 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);
}

Você também deve ser capaz de fazer isso em uma função inline. A verificação de estouro quase sempre curto-circuito após a primeira comparação. A cláusula após a && é simplesmente para que possa (no caso de um 32 bit, dois do inteiro complemento) adicionar 5 ao final de 429.496.729, mas não 6.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top