首先說一下我原來錯誤的認識
int是32個bit,
如果我們把第一位理解為符號位,那么很顯然int的范圍是-(2^31-1)~2^31-1
但是實際上我們都知道int的最小值是-2^31次。。
為什么會這樣呢。。首先對於這個問題困惑的話說明你的邏輯不夠強
因為如果第一位是符號位那么上面的分析必然是正確的。。而且按照上面的表示方法,我們顯然可以發現
有兩個零,一個是+0,一個是-0
然而實際上好像並沒有這么一說
所以說。。從這里。。正常的邏輯思維應該得出一個結論。。那就是c語言的int表示方法並不是我們想的那樣
那么我們用x表示一個值。。+,-符號來表示正負號,等號右側用來表示這個數在計算機里存儲的值。。我們都知道計算機是沒法存儲正負號的(硬件)(額似乎不太恰當)
那么根據int的表示方法的hash他是怎么工作的呢
+x=x
-x=~(x)+1
除了要注意按位取反表達式。。我們還要注意需要把規定位數的兩個數每一位對齊。。高位和過低都截斷(?)
那么這樣我們就可以發現。。-(2^31)=~(2^31)+1
這個太長啦。。我們舉一個短一點的例子來算一下
-(2^3)=~(2^3)+1=2^3
-1000=0111+1=1000
哇哦好神奇。。這個就是4位數能表示的最小負數。。4位可以表示的最小負數可以用2^3來表示
那么同理。。32位整數能表示的最小負數就可以用2^31來表示。。顯然可以存下的啊
所以說經過計算我們就發現了。。int的范圍是-(2^31)~(2^31-1)
===========================================================================
研究完了int我們再來研究一下浮點數
那么我們來研究一下float的表示方法
此時我們是按照IEEE754標准來定義存在計算機里面浮點數的數據結構
那么對於float來講。。它是一個32位浮點數
我們按照最低位是第0位來講
首先這個32bit的位串要分成三部分。。符號位。。階碼。。尾數
我解釋一下啥叫符號位。。第31位是符號位,0:+,1:-
啥是階碼呢。。。階碼是用來表示這個
1.xxx*2^x的x的大小的。。
首先這個標准規定了都用這種方式來表示浮點數
1.0是最小的。。1+1-2^(-23)是最大的基數。。(前面那個我都管它叫基數)
我用10進制的小數舉個例子。。比如說。。3位小數的最大值是多少呢。。
顯然我們知道是0.999那么其實它等於1-10^(0-3)
那么同理我們可以知道23位尾數的的小數的二進制最大小數可以表示成1-(2^(0-23))
然后我們就知道了。。那我這個x要有正有負才可以就是說。。小數點兩個方向都可以浮動
但是他的這個存的策略是。。我只存正數。。等到我要取出來計算並且表示的時候
我用一個偏移量把它拆成兩半。。一半大於零。。一半小於零
那么實際上對於float的這個尾數的存儲策略的話。。是沒有用到狀態壓縮的。。
它的尾數是多少我們就存多少。。如實復制即可
=================
那么對於浮點數這個東西我們還要注意
你怎么表示零。。
出現了1/非常小但不為零的小數=》無窮 你怎么處理
首先對於零的問題。。你尾數域默認最高有效位是1...所以沒有存它。。
但是既然最高有效位不為0.。你怎么表示真正的0呢
所以這時候他們的策略是犧牲狀態空間來特判表示0
那么對於無窮的情況呢?同理。。特判
當階碼全為零,尾數也全為零表示的真值是真正的0,並不是用很小的數逼近
當階碼全為1,尾數全為零表示的是無窮
根據符號位有,+0,-0,正無窮和負無窮
對於階碼全為1,尾數不為零的情況。。我們表示的是一個NaN非數,表示運算無效
====================
知道了上面這些我們就可以來計算float類型的值的范圍了。。
由於這里的表示方法正數和負數只差一個符號
所以我們只考慮它的絕對值的范圍就好了
即1.xxxx*2^x
那么我們知道階碼不存負數。。
所以上面那個x並不等於階碼的大小。。而是等於階碼E-127
為什么呢。。
我們知道E用8個bit存。。那么最大表示11111111=2^8-1
也就是255,那么我們知道這個數被用來特判無窮大和NaN
最小是0,用來特判0
所以對於除此之外的數。。
我們可以用1~254。。
但是你要有正有負啊。。分成兩半。。
都減去127就變成了-126~127
這樣就變成了x的范圍
知道了1.xxx的范圍和2^x的范圍。。計算就很輕松了。。
絕對值
最大是(1+1-(2^(-23)))*2^127
最小是1.0*2^(-126)?
那么再具體的話。。加上正負號就行了。。