1、浮點數
浮點數是C++
的第二組基本類型,它能夠表示帶小數部分的數字。不僅如此,浮點數的范圍也比int
更大,可以表示更大范圍的數字。
我們都知道在計算機當中,所有數據本質上都是轉化成二進制存儲的。整數很簡單,存儲的就是轉化成二進制之后的01串,那么浮點數又是如何存儲的呢?
很容易猜到的是浮點數存儲的結果也是二進制,但相比于整型直接轉化成二進制要復雜一些。
它需要先表示成下面這行式子:
這里的n即我們要存儲的浮點數,s
表示符號位,m
是尾數,而e
則是階數。
符號位很好理解,它和整型當中的符號位一樣,0表示正數,1表示負數。m表示尾數,。我們這么看很抽象,來看一個例子,比如3.0,轉化成二進制是,相當于。那么,。
我們了解了浮點數的表示方式,那么它又是如何存儲在計算機當中的呢?這需要我們進一步地剖析其中的細節。
2、關于m
首先是m
,m
被定義成一個大于等于1,小于2的小數。我們可以簡單寫成1.xx,其中xx表示的就是小數的部分。
既然它總是大于等于1,小于2的,那么它的個位一定是1,我們就可以將它省略,僅僅看之后小數的部分。小數的部分,我們同樣使用二進制來逼近。比如0.625,可以表示成0.5 + 0.125,即,表示成二進制就是,只不過這里它的最高位是從-1開始的。
以32位的浮點數為例,除去1位表示符號,8位表示階數之后,還有23位留給m。由于我們舍掉了小數點之前的1,所以我們的階數是從-1開始的,理論上等價于24個二進制位。
3、關于e
在浮點數存儲當中,e是一個無符號整數。以32位浮點數為例,e一共有8位,可以表示0-255。
但e是可以為負數的,根據IEEE 754的規定,e的真實值必須再減去一個中間數。對于8位的e,它的中間數是127。比如e的實際值是10,但是存儲的時候需要存儲成127+10=137
。
除此之外,e還有另外三種情況:
- e不全為0,或全為1時,采用上述的規則表示
- e全為0時,e等于1-127,有效數字m不再默認加上1,這樣是為了還原0.xxx的小數,以及接近于0的數
-
e全為1時,如果有效數字m全為0,表示無窮大,如果m不全為0,表示
nan
(not a number)
關于e的規則看起來有些復雜,初看覺得有些難以理解,為什么要用減去中間值的設計,而不用符號位?后來仔細思考了一下才發現,如果引入符號位很難區分0.xxx以及e就是等于0的情況,雖然也可以特判處理,但就沒有現在這樣優雅了。
覺得上文看不懂的小伙伴可以直接略過這段,畢竟這個是浮點數的實現原理,算是很底層的內容了,C++ primer上對于這部分也沒有過多闡述。
4、浮點數的使用
C++當中有兩種浮點數的書寫方式,第一種是使用常規的小數點表示法:
1
2
|
double a = 1.23; float b = 3.43; |
另外一種寫法是科學記數法,寫成:
1
2
|
double a = 2.45e8; double b = 1e-7; |
2.45e8
表示,e之后可以跟正數也可以跟負數,但數字當中不能有空格。
5、浮點數類型
和C語言一樣,C++也有三種浮點數類型:float
,double
和long double
。和整型一樣,這三種類型都是浮點數,只不過表示的范圍不同。
浮點數的范圍有兩個部分綜合決定,一個部分是有效數字。比如14179是5位有效數字,而14000只有兩位,因為后面三個0都是填充位,有效數字的位數不依賴小數點的位置。C++
當中要求,float
通常表示7位有效數字,double
通常16位位,而long double
至少和double
一樣。
另外,它們能夠表達的指數范圍至少是-37到37。一般來說,float一共是4個字節32位,而double
是8個字節64位,當然這也取決于具體的運行環境。
6、注意事項
關于浮點數的使用有幾點注意事項,千萬要注意。
-
cout
輸出浮點數會刪除結尾的0 -
書寫浮點數常量時默認為
double
類型,如果需要強制表示為float
類型,請在結尾加上后綴f或者F,如:2.34f - 由于浮點數有精度,不能直接判斷兩個浮點數是否相等,很有可能得不到預期結果,正確的做法是判斷精度范圍,
如:
1
2
3
4
5
|
double epsilon = 1e-8; // 判斷a是否和b相等 if ( abs (a - b) < epsilon) { // todo } |
判斷兩個浮點數a和b是否相等,等價于兩者的差的絕對值小于某一個精度。
范圍問題,如運行下列代碼將得到錯誤的結果:
1
2
3
4
|
float a = 2.3e22f; float b = a + 1.0f; cout << b - a << endl; |
輸出的結果將是0,因為2.3e22是一個小數點左邊有23位的數字,加上1之后,就是在第23位加上1。但是float
類型只能表示數字中的前6位或者前7位,表示不了這么高的精度,因此這個+1的操作完全沒有生效。
這個問題是一個大坑,一不小心就會中招,千萬要小心。
到此這篇關于C++浮點數類型詳情的文章就介紹到這了,更多相關C++浮點數類型內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
注:文章轉自微信公眾號:Coder梁(ID:Coder_LT)