Добавить цифру к значению int без преобразования в строку?

StackOverflow https://stackoverflow.com/questions/912279

  •  06-09-2019
  •  | 
  •  

Вопрос

Есть ли безопасный способ добавить цифру в конец целого числа без преобразования его в строку и без использования 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top