其他分享
首页 > 其他分享> > 6 信息的表示和处理_整数运算

6 信息的表示和处理_整数运算

作者:互联网

目录
有趣的现象:计算机里,两个正数相加会得出一个负数,两个负数相加得出一个正数。为什么呢?看完这章就理解了。

1 无符号数加法

无符号数加法的数学**:

举例验证:
考虑一个4位数字的表示,x=9 和 y =12 的位表示分别是[1001]和[1100],他们的和是21。5位的表示为[10101]。此时就发生溢出了。如果丢弃最高位,得到[0101],即十进制的5。 5=9+12-2^4

等同于:

对于可以用x个位表示的两个无符号数,如果没有溢出,相加结果等于他们的和。如果有溢出,结果为两数之和减去2^x

在C中,无符号数相加,不会将溢出作为错误发出信号,需要自行判断是否溢出。
检测溢出
两个无符号数相加,如果结果少于两个中较大的那个数,那就意味着发生了溢出。

2 补码加法

补码加法的数学推论:

解释下:

举例子验证:对于用4个位表示的两个有符号数:

x y x+y 截断后 溢出情况
-8:[1000] -5:[1011] -13:[10011] 3:[0011] 负溢出
-8:[1000] -8:[1000] -16:[10000] 0:[0000] 负溢出
-8:[1000] 5:[0101] -3:[1101] -3:[1101] 正常
2:[0010] 5:[0101] 7:[0111] 7:[0111] 正常
5:[0101] 5:[0101] 10:[01010] -6:[1010] 正溢出

等同于:

对于可以用x个位表示的两个有符号数,相加后:

  1. 如果没有溢出,结果等于他们的和。
  2. 如果有正溢出,结果等于和减去2^x
  3. 如果有负溢出,结果等于和加上2^x

检测溢出:

4 阿尔贝群理论

因为阿尔贝群理论,我们可以得出:

  1. (x+y)-x ,求值总能得到y,无论加法是否溢出
  2. (x+y)-y,求值总能得到x,无论加法是否溢出

5 无符号数乘法

无符号数乘法的数学公式:

等同于:

对于可以用n个位表示的两个无符号数:x,y,相乘并对结果保留n位。那么这个截断后的值等于 【x乘以y,然后对2^n取模求余】。

补充说明:

  1. 任意两个可用x个位表示的无符号数想乘,结果的位数最多可能为2x位。 例如[110] * [110] = [100100]
  2. C语言中,无符号乘法并定义为产生x位的值,等于2x位的整数乘积的低x位表示的值。【就是截断只保留低x位并作为结果】

6 补码乘法

无符号数乘法的数学推论:

等同于:

对于可以用n个位表示的两个有符号数:x,y,相乘并对结果保留n位。那么这个截断后的值等于 【x乘以y,然后对2^n取模求余,然后将转为补码】

todo 有符号数乘法的二进制如何实现的

7 无/有符号数乘法验证

8 乘以常数

了解一下背景:

  1. 整数乘法、除法运算指令慢,需要耗费更多的时钟周期。
  2. 位运算需要耗费的始时钟周期少。
  3. 用位运算和加法运算的组合来代替常数的乘法运算。左移

无符号数乘以2^n,等价左移n位

例如,假设一个程序包含表达式x*14。利用14=2³+2²+2¹,编译器会将乘法重写为 (x<<3)+(x<<2)+(x<<1),将一个乘法替换为三个移位和两个加法。无论x是无符号的还是补码, 甚至当乘法会导致溢出时,两个计算都 会得到一样的结果

更好的是,编译器还可以利用属性14=24-21,将乘法重写为(x<<4)-(x<<1) ,这时只需要两个移位和一个减法。

9 除以2的幂

1、对于无符号数
数学推论:

等同于:

无符号数用逻辑右移实现除以2^n

验证:
16/2^2 =[0001 0000] >>>2 =[0000 0100] = 4

2、对于补码
数学推论:

等同于:

  1. 当补码为负数时,移位前加一个偏置(1<<k)-1,然后再进行算术右移
  2. 当补码是正数时,跟无符号数规则一致。

注意,除以2的幂我们可以通过逻辑或算术右移实现,但是与乘法不同,该方法不能推广到除以任意常数。

10 关于整数运算的最后思考

  1. 计算机执行的“整数”运算实际上是一种模运算形式。 改为【位运算】更容易理解
  2. 表示数字的有限字长限制了可能的值的取值范围,结果运算可能溢出
  3. 补码表示提供了一种既能表示负数也能表示正数的灵活方法,同时使用了与执行无符号算术相同的位级实现,这些运算包括像加法、减法、乘法,甚至除法,无论运算数是以无符号形式还是以补码形式表示的,都有完全一样或者非常类似的位级行为。
  4. C语言中的某些规定可能会产生令人意想不到的结果,而这些结果可能是难以察觉或理解的缺陷的源头。【unsigned数据类型 很坑爹
  5. 我们特别看到了unsigned数据类型,虽然它概念上很简单,但可能导致即使是资深程序员都意想不到的行为。我们还看到这种数据类型会以出意料的方式出现,比如,当书写整数常数和当调用库函数时。

11 阶段性总结

学习完 《4 信息的表示和处理_信息存储》、《5 信息的表示和处理_整数表示》《6 信息的表示和处理_整数运算》 这三节后,应该有以下的收获:

  1. 数据的表示、数据的运算的底层实现。
  2. 补码?因为有符号数的缺陷,引入了用补码来实现有符号数(正数或者负数)
  3. 为什么会产生溢出?因为字节数是固定的,比如只分配2个字节来存储整数,如果相加结果需要用3个字节才能存储,此时就会产生溢出
  4. 为什么两个正数相加的结果可能是负数?因为溢出,产生了截断。

标签:运算,符号,处理,相加,补码,整数,溢出,乘法
来源: https://www.cnblogs.com/knowledgeispower/p/16701136.html