Anexar dígitos para um int sem converter para string?
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?
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.