在溢出的情况下,变量的值总是为负

时间:2014-03-03 10:21:19

标签: c++ c integer-overflow

它尝试解决此问题,给定N,K amd M,找到T的最大整数N*(K^T) <= MN,K and M可以是10^18的值。所以long long就足够了。 我尝试使用T

上的迭代来解决它
int T = 0;
long long Kpow = 1;
while(1)
{
  long long prod = N*Kpow;
  if(prod > M)
    break;
  T++;
  Kpow = Kpow*K;
}

但由于N*Kpow可能会超出long long的范围,因此需要使用一些大整数来处理该产品。但是我找到了一些巧妙处理这种情况的其他代码

long long prod = N*Kpow;
if(prod < 0)
  break;

即使我一直看到,在溢出中,变量的值变为负数。情况总是如此,有时甚至在溢出情况下也会出现正值?

4 个答案:

答案 0 :(得分:8)

从语言的角度来看,有符号整数溢出的行为是未定义。这意味着任何可能发生的事情 - 它可能是负面的,它可以保持不变,程序可以崩溃或者可以在线订购披萨。

在实践中最有可能发生的事情取决于您运行的处理器架构 - 因此您必须参考平台规范才能知道。

但我猜你不能保证溢出是负面的。作为一个人为的例子:

signed char c = 127;
c += 255;
std::cout << (int)c << '\n';

x86上的print 126会发生这种情况。但同样,它实际上可以做任何事情。

答案 1 :(得分:0)

没有。在溢出的情况下,变量的值 not 总是为负。

对于有符号整数,C11dr §3.7.13未定义的行为“未定义行为的一个示例是整数溢出的行为。”所以没有测试溢出后确实可以在编译器和平台上运行。

在之前检测潜在的溢出

int T = 0;
long long Kpow = 1;
long long Kpow_Max = LLONG_MAX/K;
long long prod_Max = LLONG_MAX/N;

while(1)
{
  if (Kpow > prod_Max) Handle_Overflow();
  long long prod = N*Kpow;
  if(prod > M)
    break;
  T++;
  if (Kpow > Kpow_Max) Handle_Overflow();
  Kpow = Kpow*K;
}

答案 2 :(得分:-1)

无法将此问题转换为K ^ T&lt; =(M + N - 1)/ N?

就溢出检测而言,通常执行加法和减法,好像数字是无符号的,溢出位基于有符号数学设置,并且进位/借位位基于无符号数学设置。对于乘法,结果的低阶对于有符号或无符号乘法是相同的(这就是为什么ARM cpu只有32位操作数的64位结果的有符号/无符号乘法)。如果产品太大而无法容纳在接收产品的寄存器中,则会发生溢出,例如产生39位乘积的32位乘法,应该进入32位寄存器。对于除法,如果除数为零或者商数太大而不适合接收商的寄存器,例如64位被除数除以32位除数,则会发生溢出,从而产生40位商。对于乘法和除法,只有当结果的大小适合接收结果的寄存器时,操作数是否有符号无关紧要。

答案 3 :(得分:-4)

正如任何其他具有任意长度的有符号整数的情况一样......当且仅当溢出到符号位的特定位打开时,溢出才会使数字为负。

这意味着如果你的算术结果会给你一个溢出,如果你把变量字的长度增加一倍,就会把你当前的符号位留下来,你很可能会得到一个错误的结果,那就是正。