如果我有一个表达式x + y
(在C或C ++中)x
和y
都是uint64_t
类型导致整数溢出,我该怎么检测它被(进位),位置溢出多少而不是另一个变量,然后计算余数?
答案 0 :(得分:9)
假设您使用无符号整数,则余数将已存储在x + y的总和中。无符号整数溢出导致环绕(未定义有符号整数溢出)。请参阅评论中Pascal的标准参考。
溢出只能是1位。如果添加2个64位数,则进位位不能超过1,因此您只需要检测溢出条件。
关于如何检测溢出,有一个关于该主题的先前问题:best way to detect integer overflow。
答案 1 :(得分:2)
对于z = x + y
,z存储余数。溢出只能是1位,很容易检测到。如果您正在处理有符号整数,那么如果x
和y
具有相同的符号,但z
具有相反的符号,则会出现溢出。如果x
和y
有不同的符号,则无法溢出。对于无符号整数,您只需以相同的方式检查最高位。
答案 2 :(得分:0)
C和C ++中的方法可能完全不同,因为在C ++中,您可以为您执行运算符重载工作,并将您想要保护的整数包装在某种类中(为此您需要重载必要的运算符。 C,你必须在结构中包装你想要保护的整数(以包含余数和结果)并调用一些函数来完成繁重的工作。
除此之外,两种语言中的方法是相同的:取决于您要执行的操作(在您的示例中添加),您必须弄清楚可能发生的最坏情况并处理它。
在添加的情况下,它非常简单:如果两者的总和将大于某个最大值(如果该最大值M
与其中一个的差异将是这种情况操作数大于另一个操作数)你可以计算余数 - 那个太大的部分:if ((M - O1) > O2) R = O2 - (M - O1)
(例如,如果M
为100,O1
为80,O2
为30,30 - (100 - 80) = 10
,这是余数。
减法的情况同样简单:如果你的第一个操作数小于第二个操作数,则余数是第二个减去第一个操作数(if (O1 < O2) { Rem = O2 - O1; Result = 0; } else { Rem = 0; Result = O1 - O2; }
)。
它的乘法有点困难:你最安全的选择是对值进行二进制乘法运算,并检查结果值是否超过你的位数。二进制乘法是一个很长的乘法,就像你在纸上手工进行十进制乘法一样,所以,例如,12 * 5是:
0110
0100
====
0110
0
0110
0
++++++
011110 = 40
如果你有一个四位整数,那么这里有一位溢出(即第4位为1,第5位为0.所以只有第4位计为溢出)。
对于师来说,你只需要关心除以0,大部分时间 - 其余部分将由你的CPU处理。
HTH
RLC