试图还原老师讲课的思路
Integers
Addition, negation, multiplication, shifting
Unsigned Addition
w bits + w bits : 实际结果可能是(w+1)bits,如果只用w bits存储,最高位就会被丢弃(进位)
举个例子:
两个4bit的数相加,其true sum应当是0~30,用三维图表示应当是线性增加的:如果你只用4bit来存储结果,就会出现overflow:
不管是有符号数的加法还是无符号数的加法,都是对应二进制相加,在进位,没什么区别。但是这里有一些有趣的事可以拿出来讨论下:两个负数相加会怎样?例如(-1)+(-1),怎样考虑最高位?
另外试想一下最大的整数+最小的负数会出现什么情况,怎么处理?
我们先看第二个问题,以8 Bits数为例:
最大正:0111_1111
最小负:1000_0000
相加,其结果是1111_1111,是十进制的-1,怎么解释呢?
答案是转化到补码进行运算。
此时我们看第一个问题:
-1的原码:1000_0001
-1的反码:1111_1110
-1的补码:1111_1111 (数值位取反+1)
1111_1111
+ 1111_1111
----------------
1111_1110
变回原码:1000_0010 即十进制的-2
(这里我有一个疑问,就是补码的好处就是可以符号位和数值位一样参与运算,那么当前的计算结果应为1_0111_1110,舍弃高位进位就是0111_1110,转换成原码为0000_0010,为十进制的+2,这不是溢出了吗?希望懂的人能留言讨论。)
第二个问题:
0111_1111的补码还是本身
1000_0000的补码是:1000_0001
0111_1111
+ 1000_0001
-------------------
10000_0000
高位舍弃:0000_0000 即+0,就是十进制的0
溢出问题:因为补码里,整数负数是一个循环(wrap around),所以两个正数相加溢出就变成了负数(mod 2^N ),两个负数相加溢出就会变成正数(也是mod 2^N的结果)
补充内容:
https://en.wikipedia.org/wiki/Two's_complement#Arithmetic_operations
https://www.zhoulujun.cn/html/theory/algorithm/2015_0706_3.html
Multiplication
首先,我们思考一个问题,两个数相乘需要多少位存储?
从最大数相加考虑,举个例子,3*3=9,需要4位;7*7=49.需要6;15*15=225.需要8位,。。。
可以看出m bit * n bit,需要(m+n)bit 存储。
为什么呢?
我们可以将乘法转化为加法,例如a*b,其实就是b个a相加或者说a个b相加,那么最极端的情况就是每加一次上一次结果的最高位都进位1。
如果乘数是2的倍数(2^N),直接左移N位,同理,除的话就是右移。
有些人写代码时会一直想使用上述规则。但是不要写这样的代码,1.可读性差,2,编译器会帮你做优化的。
另外,右移是可能会导致丢失精度的。
我们先看正数:
7: 0_0111
7>>1: 0_0011 = 3 接近0,向下取整
如果是负数呢?
-7:1_1001 (可以这样分析:全1为-1,我们的有2个0,即-1-6=-7)
-7>>1: 1_1100 = -4 远离0,向下取整
正数移位绝对值变小,负数移位绝对值变大。假如你需要绝对值都变小,则需要自己调整。
一句话就是:总是往左移
如果希望负数往0靠近,可以采用加上bias的方法:计算(x + (1<<k)-1) >> k
如果系统不需要负数,尽量使用unsigned,为什么呢?
1.表示的数范围更大;2. 右移时总是向0靠近
Representations in memory, pointers, strings
程序通过地址访问数据,地址是以字节为单位的。32位系统,寄存器是32位的,一次可以存4个字节;64系统寄存器是64位,一次可以存8个字节。这都不影响第一个数据的地址为0,然后一个字节一个字节增加(称为offset)。但是他们可以访问的地址数不同(CPU有一个地址寄存器),对于32位机:最大地址为4GB(2^32字节);对于64位机,最大地址为18EB(2^64 字节)。在内存里,数据是Word-Oriented。
那么,多字节的字是以怎样的顺序在内存里存储的呢?
两套系统,举个例子,
X有4个字节0x01234567,首地址为0x100
Little Endian: x86, ARM processors running Android, iOS, and Windows 低字节存在低位
Big Endian: Sun, PPC Mac, Internet 低字节存在高位
所以,1.调试时需要注意,2.跨系统时需要注意
string存储时则没有这个问题。因为string是有字符组成的,一个字符就是1字节,8位,以空字符结尾。
地址加1就是一个新的字符,不存在byte ordering的问题。
这节课主要讨论了整数的运算已经各数据类型在内存中的存在形式。下一节课将讨论浮点数。