CMU15213_Lecture_03_Bits, Bytes, and Integers cont

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014485485/article/details/82814175

 

试图还原老师讲课的思路

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的问题。

 

这节课主要讨论了整数的运算已经各数据类型在内存中的存在形式。下一节课将讨论浮点数。

猜你喜欢

转载自blog.csdn.net/u014485485/article/details/82814175