深入理解计算机系统-整数运算(2.3 Integer Arithmetic)

本文聚焦C语言中无符号与有符号数的运算。涵盖无符号数加法、有符号数加法、补码取反和无符号数乘法的公式及推导,还介绍了无符号数加法和有符号数加法的溢出检测方法,对理解C语言数值运算有重要意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.3.1 Unsigned Addition

问题引入

对于两个宽度为w-bit的无符号数x、y,有0≤x,y<2w0 \leq x,y < 2^{w}0x,y<2w

但如果计算这两个数的和,会发现:0≤x+y≤2w+1−20 \leq x+y \leq 2^{w+1} - 20x+y2w+12,表示这个和需要w+1 bit,如下图所示。

我们将这个和截断 为 w-bit,并将其视作一个无符号数,记作+wu+^u_w+wu

在这里插入图片描述

无符号数加法

公式

对于无符号数x、y,如果0≤x,y<2w0 \leq x,y < 2^{w}0x,y<2w,则有:
x+wuy={x+y,x+y<2w(Normal)x+y−2w,2w≤x+y<2w+1(Overflow)(无符号数加法-公式1) x +^u_w y = \begin{cases} x + y, & x + y < 2^w(Normal) \\ x + y - 2^w, & 2^w \leq x + y < 2^{w+1}(Overflow) \end{cases} \tag{无符号数加法-公式1} x+wuy={x+y,x+y2w,x+y<2w(Normal)2wx+y<2w+1(Overflow)(无符号数加法-公式1)
该公式可以统一为:
x+wuy=(x+y) mod 2w(无符号数加法-公式2) x +^u_w y = (x + y) \ mod \ 2^w \tag{无符号数加法-公式2} x+wuy=(x+y) mod 2w(无符号数加法-公式2)

推导

如果x+y<2wx + y < 2^wx+y<2w,那么得到的w+1 bit的和的最高位为0,将这个和截断为w-bit并不影响它的值;

如果2w≤x+y<2w+12^w \leq x + y < 2^{w+1}2wx+y<2w+1,那么得到的w+1 bit的和的最高位为0,将这个和截断为w-bit时,需要舍弃最高位的1,即减2w(或mod 2w

溢出检测

溢出

如果算术运算的结果无法适应数据类型的字长限制时,被称之为溢出

由于C语言对于溢出并不会提示错误信息,因此需要一些方法来检测是否发生溢出。

方法

对于0≤x,y<UMaxw0 \leq x,y < UMax_w0x,y<UMaxw,定义$ s \doteq x +^u_w y$;

则有: s 溢出,当且仅当$ s < x 或 s < y$,即s小于x或y中的任意一个

推导

$$
\because s 溢出 \
\therefore s = x + y - 2^w \

\because y < 2^w \
\therefore y - 2^w < 0 \

\therefore s = x + y - 2^w < x

\tag{溢出检测-推导}
$$

Modular addition

阿贝尔群

  • 可交换、连续
  • 有一个确定的元素0,并且每个元素都有一个加性逆(additive inverse)

公式

对于任意的0≤x<2w0 \leq x < 2^w0x<2w,x的无符号负数(加性逆)为:
−wu={x,x=02w−x,x>0(Modular addition-公式) -^u_w = \begin{cases} x, & x = 0 \\ 2^w -x, & x>0 \end{cases} \tag{Modular addition-公式} wu={x,2wx,x=0x>0(Modular addition-公式)

推导

  • x = 0时,其加性逆明显为0
  • 当x > 0时,对于2w−x2^w-x2wx,有0<2w−x<ww0 < 2^w -x < w^w0<2wx<ww;并且(x+2w−x) mod 2w=2w mod 2w=0(x + 2^w - x) \ mod \ 2^w = 2^w \ mod \ 2^w = 0(x+2wx) mod 2w=2w mod 2w=0

2.3.2 Two’s-Complement Addition

问题引入

与无符号数的加法一样,在进行有符号数的加法时,我们也需要考虑运算的结果是否会太大或太小。

对于−2w−1≤x,y≤2w−1−1-2^{w-1} \leq x, y \leq 2^{w-1} -12w1x,y2w11,它们的和的范围为−2w≤x+y≤2w−1-2^w \leq x+y \leq 2^w -12wx+y2w1,这个运算的结果需要w + 1 bit才能完全表示。

我们将这个和截断 为w-bit,视作有符号数,记作+wt+^t_w+wt

有符号数加法

公式

对于−2w−1≤x,y≤2w−1−1-2^{w-1} \leq x, y \leq 2^{w-1} -12w1x,y2w11
x+wty={x+y−2w,2w−1≤x+y(PositiveOverflow)x+y,−2w≤x<2w−1(Normal)x+y+2w,x+y<−2w(NegativeOverflow)(有符号数加法-公式) x +^t_w y = \begin{cases} x + y - 2^w, & 2^{w-1} \leq x + y(Positive Overflow) \\ x + y, & -2^w \leq x < 2^{w-1} (Normal) \\ x + y + 2^w, & x + y < -2^w(Negative Overflow) \end{cases} \tag{有符号数加法-公式} x+wty=x+y2w,x+y,x+y+2w,2w1x+y(PositiveOverflow)2wx<2w1(Normal)x+y<2w(NegativeOverflow)(有符号数加法-公式)

推导

原理

由于有符号数的加法与无符号数的加法在bit层级的表示是一样的;

因此,在计算+wt+^t_w+wt时,可以按如下步骤进行操作:

  1. 将运算数转为无符号数
  2. 执行无符号数的加法
  3. 将结果转为有符号数

x+wty=U2Tw(T2Uw(x)+wuT2Uw(y))x +^t_w y = U2T_w(T2U_w(x) +^u_w T2U_w(y))x+wty=U2Tw(T2Uw(x)+wuT2Uw(y))

推导过程

x+wty=U2Tw(T2Uw(x)+wuT2Uw(y))∵T2Uw(x)=xw−12w+x=U2Tw[(xw−12w+x+yw−12w+y) mod 2w]∵x+wuy=(x+y) mod 2w=U2Tw[(x+y) mod 2w]∵xw−1 mod 2w=0(有符号数加法-推导) \begin{aligned} x +^t_w y &= U2T_w(T2U_w(x) +^u_w T2U_w(y)) & \because T2U_w(x) = x_{w-1}2^w + x \\ &= U2T_w[(x_{w-1}2^w + x + y_{w-1}2^w +y) \ mod \ 2^w] & \because x +^u_w y = (x + y)\ mod \ 2^w \\ &= U2T_w[(x + y) \ mod \ 2^w] & \because x_{w-1} \ mod \ 2^w = 0 \end{aligned} \tag{有符号数加法-推导} x+wty=U2Tw(T2Uw(x)+wuT2Uw(y))=U2Tw[(xw12w+x+yw12w+y) mod 2w]=U2Tw[(x+y) mod 2w]T2Uw(x)=xw12w+xx+wuy=(x+y) mod 2wxw1 mod 2w=0(有符号数加法-推导)

4种情况

预备知识:

  • TMaxw≐∑i=0w−22i=2w−1−1TMax_w \doteq \sum_{i=0}^{w-2}{2^i} = 2^{w-1} -1TMaxwi=0w22i=2w11

U2Tw(u)={u,u≤TMaxu−2w,u>TMax(U2Tw) U2T_w(u) = \begin{cases} u, & u \leq TMax \\ u-2^w, & u > TMax \end{cases} \tag{$U2T_w$} U2Tw(u)={u,u2w,uTMaxu>TMax(U2Tw)

做如下定义:

z≐x+y,z′≐z mod 2w,z′′≐U2Tw(z′)z \doteq x +y,z' \doteq z \ mod \ 2^w ,z'' \doteq U2T_w(z')zx+y,zz mod 2wz′′U2Tw(z),即z′′=x+wtyz'' = x +^t_w yz′′=x+wty

那么会有以下4种情况,与图片对应:

在这里插入图片描述

对应图中Casez的范围z’的范围z’'的范围
1−2w≤z<−2w−1-2^w \leq z < -2^{w-1}2wz<2w1∵z′=z+2w\because z' = z + 2^wz=z+2w
∴0≤z′<−2w−1+2w=2w−1\therefore 0 \leq z' < -2^{w-1} + 2^w = 2^{w-1}0z<2w1+2w=2w1
z′′=z′=z+2wz'' = z' = z + 2^wz′′=z=z+2w
2−2w−1≤z<0-2^{w-1} \leq z < 02w1z<0∵z′=z+2w\because z' = z + 2^wz=z+2w
∴−2w−1+2w=2w−1≤z′<2w\therefore -2^{w-1} + 2^w = 2^{w-1} \leq z' < 2^w2w1+2w=2w1z<2w
z′′=z′−2w=z+2w−2w=zz'' = z' - 2^w = z + 2^w - 2^w = zz′′=z2w=z+2w2w=z
30≤z<2w−10\leq z <2^{w-1}0z<2w1z′=zz' = zz=zz′′=z′=zz'' = z' = zz′′=z=z
42w−1≤z<2w2^{w-1} \leq z < 2^w2w1z<2wz′=zz' = zz=zz′′=z′−2wz'' = z' - 2^wz′′=z2w

溢出检测

方法

对于TMinw≤x,y≤TMaxwTMin_w \leq x,y \leq TMax_wTMinwx,yTMaxw,定义s≐x+wtys \doteq x +^t_w ysx+wty,则其溢出检测为:

  • 正溢出(positive overflow):当且仅当 x > 0 并且 y > 0,但s≤0s \leq 0s0
  • 负溢出(negative overflow):当且仅当 x < 0 并且 y < 0,但s≥0s \geq 0s0

图例

在这里插入图片描述

2.3.3 Two’s-Complement Negation

公式

对于TMinw≤x≤TMaxwTMin_w \leq x \leq TMax_wTMinwxTMaxw,存在对于+wt+^t_w+wt的加性逆,记作−wt-^t_wwt,有:
−wtx={TMinw,x=TMinw−x,x>TMinw(Two’s-Complement Negation-公式) -^t_wx = \begin{cases} TMin_w, & x = TMin_w \\ -x, & x > TMin_w \end{cases} \tag{Two’s-Complement Negation-公式} wtx={TMinw,x,x=TMinwx>TMinw(Two’s-Complement Negation-公式)

推导

  1. x=TMinwx = TMin_wx=TMinw时:

∵TMinw+TMinw=−2w−1+(−2w−1)=−2w∴发送负溢出∴TMinw+wtTMinw=−2w+2w=0(Two’s-Complement Negation-推导) \because TMin_w + TMin_w = -2^{w-1} + (-2^{w-1}) = -2^w \\ \therefore 发送负溢出 \\ \therefore TMin_w +^t_w TMin_w = -2^w + 2^w = 0 \tag{Two’s-Complement Negation-推导} TMinw+TMinw=2w1+(2w1)=2w发送负溢出TMinw+wtTMinw=2w+2w=0(Two’s-Complement Negation-推导)

  1. x>TMinwx > TMin_wx>TMinw 时,-x能被表示为一个w-bit的有符号数。

bit表示

方法一

方法

求出有符号数的反码,再将其加一。

在C语言中,-x~x + 1具有相同的值

示例

在这里插入图片描述

方法二

方法

将有符号数分成两部分:

记k为最右侧的值为1的bit位置,则x⃗=[xw−1,xw−2,...,xk+1,1,0,...,0](x≠0)\vec{x} = [x_{w-1}, x_{w-2}, ..., x_{k+1}, 1, 0, ..., 0](x \neq 0)x=[xw1,xw2,...,xk+1,1,0,...,0](x=0)

则有符号数的加性逆为−wtx=[∼xw−1,∼xw−2,...,∼xk+1,1,0,...,0]-^t_wx = [\sim x_{w-1}, \sim x_{w-2}, ..., \sim x_{k+1}, 1, 0, ..., 0]wtx=[xw1,xw2,...,xk+1,1,0,...,0]

示例

实例中,最右侧的值为1的bit标为斜体

在这里插入图片描述

2.3.4 Unsigned Multiplication

问题引入

对于w-bit的无符号整数x,y,有0≤x,y≤2w−1−10 \leq x,y \leq 2^{w-1} -10x,y2w11

它们的乘积的范围是:0≤x×y≤(2w−1−1)2=22w−2w+1+10 \leq x \times y \leq (2^{w-1} -1)^2 = 2^{2w} -2^{w+1} + 10x×y(2w11)2=22w2w+1+1,需要2w-bit来表示。

在C语言中进行无符号数的乘法时,会将生产的2w-bit的乘积截取低w-bit来做为运算结果,将截断后的结果记作x∗wuyx *^u_w yxwuy

截取低w-bit的方法是将乘积模上2w

公式

对于0≤x,y≤UMax0 \leq x,y \leq UMax0x,yUMax
x∗wuy=(x×y) mod 2w(无符号数乘法-公式) x *^u_w y = (x \times y) \ mod \ 2^w \tag{无符号数乘法-公式} xwuy=(x×y) mod 2w(无符号数乘法-公式)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值