C語言浮點數運算

來源:互聯網
上載者:User

   C語言標準C89裡規定了3種浮點數,float型、double型和long double型,常見的浮點型長度為float型佔4個位元組,double型佔8個位元組,long double型長度要大於等於double型,下面將以float型為例進行介紹,double型和long double型只是比float型位元長,原理是一樣的 。

  float型可以表示的十進位範圍是-3.402823466e38~3.402823466e38,而作為同為4個位元組的定點數卻只能表示-2147483648~2147483647的範圍,使用同樣的記憶體空間,浮點數卻能比定點數表示大得多的範圍,這是不是太神奇了?既然浮點數能表示這麼大的範圍,那麼我們為何不使用浮點數來代替定點數呢?先不說浮點數實現起來比較複雜,有些處理器還專門配置了硬體浮點運算單元用於浮點運算,主要原因是浮點數根本就無法取代定點數,因為精度問題。魚和熊掌不可兼得,浮點數表示了非常大的範圍,但它失去了精度。

ANSI/IEEE Std 754-1985標準
  IEEE 754是最廣泛使用的二進位浮點數算術標準,被許多CPU與浮點運算器所採用。IEEE 754規定了多種表示浮點數值的方式,下面介紹32位二進位的float浮點類型。它被分為3個部分,分別是符號位S(sign bit)、指數偏差E(exponent bias)和小數部分F(fraction),這三部分都是對應二進位碼的。

 

  浮點表示的一般形式為(科學技術法規則):R=(S) * (1 + F) * 2e (R:實數       S:正負符號      F:小數部分     e:指數,不同於指數偏差)。

  • 符號位S:佔1位,0代表浮點數是正數,1代表浮點數是負數。
  • 指數偏差E:佔8位,範圍是0~255,e = E - 127,e為正值表明轉換成二進位碼後,按科學計數法表達時向左移動了e位, 負值表明向右移動了e位。
  • 小數部分F:佔23位,實際上是將浮點數轉換成二進位碼,再按科學計數法表達,將其小數部分存在F上,由於二進位碼按科學計數法表達後,只要值不為0,整數部分就必然為1,所以可以省略整數部分。

  例如,3.75的二進位碼為11.11,將該二進位碼按科學計數法表達為1.111,則向左移動了1位,即e=1,E=e+127=128,F記錄的便是小數部分,實際為111000...000。

  下面介紹一下小數部分轉換為二進位碼的方式。類似於整數的形式(如7 = 22 + 21 + 20),小數部分的轉換形式為2-1、2-2、2-3、2-4......,例如0.5 = 2-1,即二進位碼為0.1,0.05 = 2-5 + 2-6 + 2-9 + 2-10 + 2-13 + 2-14 +...... (可無限迴圈),即二進位碼為0.00001100110011......。如果都以16位計,那麼7的二進位碼為0000000000000111,0.5的二進位碼為0.1000000000000000,0.05的二進位碼為0.0000110011001100。這是如何換算出來的呢?且看下面的演算法便知:

  換算0.5,乘法結果初始為0.5,所有乘數為2,每次用乘法結果 * 乘數,得到新的乘法結果,結果中的整數部分被提取出來,剩餘的小數部分繼續參加下一次乘法運算,直到剩餘小數部分為0,或者無終點(無限迴圈)。根據表格中的整數部分可知,二進位為0.1。

整數部分 乘數 乘法結果 剩餘小數部分
0. 2 0.5  0.5
1   1 0
     結束  

  換算0.05,乘法結果初始為0.05,所有乘數為2,每次用乘法結果 * 乘數,得到新的乘法結果,結果中的整數部分被提取出來,剩餘的小數部分繼續參加下一次乘法運算,直到剩餘小數部分為0,或者無終點(無限迴圈)。根據表格中的整數部分可知,二進位為0.00001100110011......。

整數部分 乘數 乘法結果 剩餘小數部分
0. 2 0.05  0.05
0 2 0.1 0.1
0 2 0.2 0.2 
0 2 0.4 0.4
0 2 0.8  0.8
1 2 1.6 0.6
1 2 1.2 0.2
0 2 0.4 0.4
0 2 0.8 0.8
1  2 1.6 0.6
1   1.2 0.2
    無限迴圈  

例1:float型浮點數125.5轉化成32位二進位浮點數。

  125.5的整數和小數部分的二進位碼分別為1111101和0.1,於是125.5的二進位碼為1111101.1,按科學技術法寫為1.1111011*26,即向左移6位,則e=6,E=e+127=133,133的二進位碼為10000101。而1.1111011把整數部分的1去掉後,剩下小數部分為1111011,之後補0至23位,構成F。所以125.5的32位二進位浮點數為:
0  10000101  11110110000000000000000

例2:float型浮點數0.5轉化成32位二進位浮點數。

  類似的,0.5的二進位碼為0.1,按科學技術法寫為1.0*2-1,即向右移1位,則e=-1,則E=e+127=126,126的二進位碼為01111110。而1.0把整數部分的1去掉後,剩下小數部分為0,之後補0至23位,構成F。所以0.5的32位二進位浮點數為:
0  01111110  00000000000000000000000

幾個特殊的情形

  • E=0,F=0時,表示浮點數0,此時浮點數受S影響,表現出+0和-0兩種0,但數值是相等的。比如位元0x00000000表示+0,位元0x80000000表示-0。
  • E=0,F不等於0時,浮點數為(S) * (F) * 2e,注意e為-126,而不是0-127=-127,而且F是0.xxx格式而不是1.xxx格式,比如0x00000001的浮點數為2-126*2-23=1.4012984643248170709237295832899e-45,而不是20-127*(1+2-23)。E從0變為1,不會產生增加2倍的關係,而是計算公式改變了(恢複正常公式)。
  • E=255,F不等於0時,表示非數值,也就是說是非法數,例如0x7F800001。
  • E=255,F=0時,表示無窮大的數,此時浮點數受S影響,例如0x7F800000表示正無窮大,0xFF800000表示負無窮大。做除法時,如果除以0時,結果將被記作0x7F800000。

浮點數的精度

  從前文中可以看到,1.xxx這類浮點數中,F部分最小的是2-23,對應的十進位數為1.00000011920928955078125,可以精確表示到小數點後23位,但是一些C語言書上卻說float型的有效位只有6~7位,這是為什麼呢?原因在於二進位小數與十進位小數沒有完全一一對應的關係,二進位小數相比十進位小數來說,是離散而不是連續的,我們來看看下面這些數字:

二進位小數    十進位小數
2-23       1.00000011920928955078125
2-22       1.0000002384185791015625
2-21       1.000000476837158203125
2-20       1.00000095367431640625
2-19       1.0000019073486328125
2-18       1.000003814697265625

  這裡只需要關注F,上面列出了1.xxx這類浮點數中的6個最小的二進位小數,及其對應的十進位數。可以看到使用二進位所能表示的最小小數是1.00000011920928955078125,其次是1.0000002384185791015625,這兩個數之間是有間隔的,如果想用二進位小數來表示8位有效數(只算小數部分,小數點前面的1是隱藏的預設值)1.00000002、1.00000003、1.00000004......這些數是無法辦到的,而7位有效數1.0000001可以用2-23來表示,1.0000002可以用2-22來表示,1.0000003可以用2-23+2-22來表示。從這個角度來看,float型所能精確表示的位元只有7位,7位之後的數雖然也是精確表示的,但卻無法表示任意一個想表示的數值。

  但還是有一些例外的,比如說7位有效數1.0000006這個數就無法用F表示,這也表明二進位小數對於十進位小數來說相當於是離散的,剛好湊不出1.0000006這個數,從這點來看float型所能精確表示的位元只有6位。因此float型的有效位元是6~7位,但這個說法應該不是非常準確,準確來說應該是6位,C語言的標頭檔中規定也是6位。對於一個很大的數,例如1234567890,它是由於指數E係數而被放大了的,但它的有效位仍然是F所能表示的6~7位有效數字。1234567890用float表示後為1234567936,只有高7位是有效位,後3位是無效的。int型可以準確的表示1234567890,而float浮點數則只能近似的表示1234567890,精度問題決定了float型無法取代int型。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.