在 x + y 中获取"carry"

Getting "carry" in x + y

本文关键字:获取 carry      更新时间:2023-10-16

可能重复:
检测C/C++中整数溢出的最佳方法

如果我有一个表达式x + y(在C或C++中),其中xy都是导致整数溢出的uint64_t类型,我如何检测它溢出了多少(进位),放在另一个变量中,然后计算余数?

假设使用的是无符号整数,则余数将存储在x+y的和中。无符号整数溢出导致环绕(有符号整数溢出未定义)。请参阅评论中Pascal的标准参考。

溢出只能是1位。如果你加上2个64位的数字,进位不能超过1个,所以你只需要检测溢出情况。

关于如何检测溢出,之前有一个关于该主题的问题:检测整数溢出的最佳方法。

对于z = x + y,z存储余数。溢出只能是1位,而且很容易检测。如果处理有符号整数,那么如果xy的符号相同,而z的符号相反,则会出现溢出。如果xy的符号不同,则不能溢出。对于无符号整数,您只需以相同的方式检查最高有效位。

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