Добавить цифру к значению int без преобразования в строку?
Вопрос
Есть ли безопасный способ добавить цифру в конец целого числа без преобразования его в строку и без использования stringstreams ?
Я попытался найти в Google ответ на этот вопрос, и большинство решений предлагали преобразовать его в строку и использовать stringstreams, но я хотел бы сохранить его как целое число, чтобы обеспечить целостность данных и избежать преобразования типов.
Я также прочитал решение, в котором предлагалось умножить значение int на 10, а затем добавить цифру, однако это может привести к переполнению целого числа.
Безопасно ли это делать или есть лучший способ для этого?И если я сделаю это, умножив на 10 и добавив решение с цифрами, какие меры предосторожности я должен предпринять?
Решение
Ваш лучший выбор - это умножение на 10 и сложение полученного значения.Вы могли бы сделать наивный чек вот так:
assert(digit >= 0 && digit < 10);
newValue = (oldValue * 10) + digit;
if (newValue < oldValue)
{
// overflow
}
Другие советы
Для предотвращения переполнения:
if ((0 <= value) && (value <= ((MAX_INT - 9) / 10))) {
return (value * 10) + digit;
}
Вместо MAX_INT вы могли бы использовать std::numeric_limits<typeof(value)>::max()
или аналогичный, для поддержки типов, отличных от 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)
Вот лучшая и более пуленепробиваемая реализация, чем та, которая была принята в качестве ответа, который также является быстрым:
#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);
}
Вы также должны быть в состоянии превратить это во встроенную функцию.Проверка переполнения почти всегда приводит к короткому замыканию после первого сравнения.Предложение после &&
это просто для того, чтобы вы могли (в случае 32-разрядного числа, дополняемого двумя) добавить 5 в конец 429496729, но не 6.