10

有没有一种安全的方法可以在整数末尾添加一个数字而不将其转换为字符串并且不使用 stringstreams ?

我试图用谷歌搜索这个答案,大多数解决方案都建议将其转换为字符串并使用字符串流,但我想将其保留为整数以确保数据完整性并避免转换类型。
我还阅读了一个解决方案,该解决方案建议将 int 乘以 10,然后添加数字,但这可能会导致整数溢出。
这是安全的还是有更好的方法来做到这一点?如果我这样做乘以 10 并添加数字解决方案,我应该采取哪些预防措施?

4

4 回答 4

26

您最好的选择是乘以 10 并加上该值。您可以像这样进行天真的检查

assert(digit >= 0 && digit < 10);
newValue = (oldValue * 10) + digit;
if (newValue < oldValue)
{
    // overflow
}
于 2009-05-26T19:32:46.220 回答
3

为防止溢出:

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

代替 MAX_INT,您可以使用std::numeric_limits<typeof(value)>::max()或类似的方法来支持除 int 以外的类型。

于 2009-05-26T20:23:47.367 回答
2
  断言(数字 >= 0 && 数字 < 10);
  新值 = 10 * 旧值;
  如果(旧值 < 0){
    新值-=数字;
  } 别的 {
    新值 += 数字;
  }

  // 检查溢出 SGN(oldvalue) == 0 || SGN(新值) == SGN(旧值)
于 2009-05-26T20:35:26.593 回答
2

这是一个比被接受为也很快的答案的更好和更防弹的实现:

#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。

于 2010-01-28T05:24:02.303 回答