天天看點

為什麼使用%lf 讀取double型的值,而用%f 進行顯示?

注意scanf函數和printf函數是不同尋常的函數,因為它們都沒有将函數的參數限制為固定數量。scanf函數和printf函數又可變長度的參數清單。當調用帶可變長度參數清單的函數時,編譯器會安排float參數自動轉換成為double類型,其結果是printf函數無法區分float型和double型的參數。是以在printf函數調用中%f既可以表示float型又表示double型的參數。

      另一方面,scanf函數是通過指針指向變量的。%f告訴scanf函數在所傳位址位置上存儲一個float型值,而%lf告訴scanf函數在所傳位址位置上存儲一個double型值。這裡float和double的差別是非常重用的。如果給出了錯誤的轉換說明,那麼scanf函數将可能存儲錯誤的位元組數量(沒有提到的是,float型的為模式可能不同于double型的位模式)。

       另外曆史原因C語言中浮點計算一直采用雙精度的形式。

       附錄說明:IEEE浮點标準的兩種主要的浮點數格式:單精度(32位)和雙精度(64位)。數值以科學計數法的形式存儲,每一個數都是由3部分組成:符号、指數和小數。

EEE754浮點标準

EEE754标準在表示浮點數時,每個浮點數均由三部分組成:符号位S,指數部分E和尾數部分M。

我們知道10進制數的科學計數法如A= -3.5×105 

這裡最前面有一個負号,3.5是尾數,兩個有效數字,後面以10為基數的指數為5。

我們可以将它表示為 -3.5E5 

同樣,二進制數也可以用科學計數法規格化表示,比如5這個數,如果用二進制表示的話,整型為101,如果用科學計數法則可以表示為 1.25×24 ,這裡用的是十進制,将尾數換成二進制就是1.01(就是101向前移兩位小數點,和十進制完全相同),後面的指數4換成二進制則是10,那我們将其用二進制的科學計數法就可以寫成1.01E10。 

當我們依照這種計數法給一個數字确定其精度(有效位)後,就可以用一定長度的1和0的位串來表示一個實數了。 

浮點數一般采用以下四種基本格式:

(1)單精度格式(32位):除去符号位1位後,E占8位,M占23位。

(2)擴充單精度格式:E>=11位,M31位。

(3)雙精度格式:(64位);E=11位,M=52位。

(4)擴充雙精度格式:E>=15位,M>63位。

我們最重要的是掌握單精度格式的表示法。在IEEE754标準中,約定小數點左邊隐含有一位,通常這位數就是1,這樣實際上使尾數的有效位數為24位,即尾數為1.M。指數的值在這裡稱為階碼,為了表示指數的正負,是以階碼部分采用移碼表示,移碼值為127,階碼值即從1到254變為-126至+127,在 IEEE754中所有的數字位都得到了使用,明确地表示了無窮大和0,并且還引進了"非規格化數",使得絕對值較小的數得到更準确表示。請看下表:

S(1位)      E(8位)             M(23位)             N(32位)  

符             0                 0            (-1)S·2E-127·(1.M) 為規格化數                                     

              0              不等于0       (-1)S·2-126·(0.M) 為非規格化數

号        1到254之間          不等于0       (-1)S·2E-127·(1.M) 為規格化數

             255             不等于0     NaN(非數值) 

位            255                 0            無窮大  

其中紅色字0、1表示隐含位,注意當數字N為非規格化數或是0時,隐含位是0。

記住了上面的表格就能算出所有IEEE标準的單精度二進制浮點數了,我們重點要會計算規格化數字的雙向轉換,并且了解二進制浮點數表示法的思想。