它尝试解决此问题,给定N,K amd M
,找到T
的最大整数N*(K^T) <= M
。 N,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;
即使我一直看到,在溢出中,变量的值变为负数。情况总是如此,有时甚至在溢出情况下也会出现正值?
答案 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)
正如任何其他具有任意长度的有符号整数的情况一样......当且仅当溢出到符号位的特定位打开时,溢出才会使数字为负。
这意味着如果你的算术结果会给你一个溢出,如果你把变量字的长度增加一倍,就会把你当前的符号位留下来,你很可能会得到一个错误的结果,那就是正。