[toc]
概 述
本章主要講了整型和浮點型的各種用法。但我更想強調的是使用數據時可能會出現的誤區。
很多符合人常識的數學計算,在計算機中卻可能得到不可思議的結果。
比如兩個整數相加或者相乘,可能得到一個負數值,兩個負數值相加,可能得到一個正值。
所以我會在下一個靈魂拷問部分,把公開課上教授舉出的各種puzzle都總結一下,如果你每個題都做對了,那么就說明掌握的非常好,不需要細看這篇博客了。
這本書主要基于 x86-64位,所以指針大小為8個字節,int類型為4個字節,float也是4個字節。
這篇不是傻瓜型總結,要看的話需要一定的C語言基礎。
配套課程實驗 DataLab請看我的博客:深入理解計算機系統 CSAPP DataLab 2019.
參考資料:B站深入理解計算機系統公開課(有中文字幕,強烈推薦)
整型
整型 靈魂拷問
// initialization
int x = foo();
int y = bar();
unsigned ux = x;
unsigned uy = y;
x, y為int整型,ux,uy為無符號整型。x,y的值可能是,int類型取值范圍內的任何一個數。
請問下列問題是否對所有符號要求的 x,y 都成立
已知
x < 0
,可以得到(x * 2) < 0
所有 ux 滿足
ux >= 0
已知 `x & 7 == 7
,可以得到
(x << 30) < 0``所有 ux 滿足
ux >= -1
已知
x > y
,可以得到-x < -y
所有 x 滿足
x * x >= 0
已知
x > 0 && y > 0
,可以得到x + y > 0
已知
x >= 0
,可以得到-x <= 0
已知
x <= 0
,可以得到-x >= 0
所有x 滿足
(x | -x) >> 31 == -1
整型 靈魂拷問答案
- False, 反例:Tmin,也就是INT_MIN
- True, 無符號數一定大于0
- True, 向左偏移后,符號位為1,所以一定小于0
- False,有符號和無符號數在運算得時候,會自動講有符號轉換成無符號數。-1是最大的無符號數
- False, 反例:假設
x == 0, y == Tmin
,x,y的相反數是x,y本身,所以后者不成立 - False
- False,
Tmax + 1 == Tmin
- True
- False, 只有一個反例,那就是
x == Tmin
- False, 唯一反例,
x == 0
整型學習要點
- 64位和32位區別是什么?
64和32位,可以理解為指針的大小不同。32位系統,指針是4個字節,64位系統,指針是8個字節。
學過C都知道,指針上面保存的是地址,那么32位系統,指針的地址只有32位地方放,我們可以算一下最多存多少東西:
32位存放地址,有2 ^ 32種可能性,之后除以3個1024得到多少個G。最后得到4個G。也就是說32位系統的內存最多就是4G,多了就是浪費。64位就不一樣了,當然我們現在的電腦,根本沒法把2^64的內存填滿。
- 溢出
整型溢出的所有處理方法都是截斷,而且C編譯器不會給出任何的溢出警告。無論是乘法還是加法,只要超出了int的32位,都會只保留最低的32位,保留下來的符號位是1變成了負數,是0就變成非負數。
- 補碼
請點鏈接,我自己的寫的另一篇博客:為什么計算機使用補碼
- Tmin Tmax
Tmin 是int的最小的數: 0x80000000
Tmax 是int的最大的數: 0x7FFFFFFF
對一個整數取相反數: ~x + 1,我也不知道為啥,就當數學定理背過就行了
所有整數有兩個數的相反數是其本身: 0 和 Tmin,因為正數范圍內沒有一個數是和Tmin對應的。
他們之間還有一個關系 Tmax + 1 == Tmin
- 移位
左移位比較簡單,就移動就行了,右邊多出來的用 0 填補。
右移位看情況,不同的機器操作不一樣。但是絕大多數情況下,右移位是算術移位,那就是左邊多出來的位使用符號位填補。
int是32位,如果你移動50位會怎么樣?正常情況下系統會移動 (x mod 32) 位。也就是 50 % 32 == 18
浮點型
很多人(比如我)對浮點型的了解很有限,所以這里就講具體做法吧,就不上題了
浮點型學習要點
前思后想不如直接提供一個講的好的鏈接:IEEE浮點數
浮點數這個東西,其實在實際項目里面很難遇到,可能數據分析啥的用的比較多,但是正常的項目其實整型完全可以做,所以我這里就講一下要點。
- 組成
浮點數是由3部分組成的,符號位,指數位,尾數位。
用float舉例,符號位占1位,指數占8位,尾數占23位。
這8位指數,你要在中間割一刀,這一刀就是小數點,小數點左側的數就像整型二進制一樣,從小到大代表 1,2,4,8。但是小數點右邊的數正好相反,代表,1/2,1/4,1/8,1/16。
- 特性
如果你畫一個數軸,然后把float能代表的點都畫在上面,你會很明顯的發現,越靠近0,點越密集,越遠離0,點越稀疏。
這是因為尾數是一個固定的數,float從0到正無窮的過程中,指數會慢慢變大,一開始指數很小,所以點和點之間貼的特別近。但是之后指數爆炸增長,所以點和點離得特別遠。在上部分組成里面說的,指數部分是有小數點的,那么就容易理解,如果你這個數很大,那么精確性會變差,因為好多指數位都給了小數點左側用,右側少了自然不精確,反之亦然。
- 結合律
浮點數不滿足結合律。具體請看反例
(3.14 + 1e10) - 1e10 == 0
3.14 + (1e10 - 1e10) == 3.14
(1e20 * 1e20) * 1e-20 != 1e20
(1e20 * 1e20) * 1e-20 == infinite
1e20 * (1e20 * 1e-20) == 1e20