C語言中的小數(float,double)

c語言小新 發佈 2024-04-28T22:37:22.834804+00:00

小數分為整數部分和小數部分,它們由點號.分隔,例如 0.0、75.0、4.023、0.27、-937.198 -0.27 等都是合法的小數,這是最常見的小數形式,我們將它稱為十進位形式。此外,小數也可以採用指數形式,例如 7.25×102、0.0368×105、100.

小數分為整數部分和小數部分,它們由點號.

分隔,例如 0.0、75.0、4.023、0.27、-937.198 -0.27 等都是合法的小數,這是最常見的小數形式,我們將它稱為十進位形式。

此外,小數也可以採用指數形式,例如 7.25×102、0.0368×105、100.22×10-2、-27.36×10-3 等。任何小數都可以用指數形式來表示。

C語言同時支持以上兩種形式的小數。但是在書寫時,C語言中的指數形式和數學中的指數形式有所差異。

C語言中小數的指數形式為:

aEn 或 aen

a 為尾數部分,是一個十進位數;n 為指數部分,是一個十進位整數;Ee

是固定的字符,用於分割尾數部分和指數部分。整個表達式等價於 a×10n。

指數形式的小數舉例:

  • 2.1E5 = 2.1×105,其中 2.1 是尾數,5 是指數。
  • 3.7E-2 = 3.7×10-2,其中 3.7 是尾數,-2 是指數。
  • 0.5E7 = 0.5×107,其中 0.5 是尾數,7 是指數。


C語言中常用的小數有兩種類型,分別是 float 或 double;float 稱為單精度浮點型,double 稱為雙精度浮點型。

不像整數,小數沒有那麼多么蛾子,小數的長度是固定的,float 始終占用4個字節,double 始終占用8個字節。

小數的輸出

小數也可以使用 printf 函數輸出,包括十進位形式和指數形式,它們對應的格式控制符分別是:

  • %f 以十進位形式輸出 float 類型;
  • %lf 以十進位形式輸出 double 類型;
  • %e 以指數形式輸出 float 類型,輸出結果中的 e 小寫;
  • %E 以指數形式輸出 float 類型,輸出結果中的 E 大寫;
  • %le 以指數形式輸出 double 類型,輸出結果中的 e 小寫;
  • %lE 以指數形式輸出 double 類型,輸出結果中的 E 大寫。


下面的代碼演示了小數的表示以及輸出:


#include <stdio.h>
#include <stdlib.h>
int main()
{
 float a = 0.302;
 float b = 128.101;
 double c = 123;
 float d = 112.64E3;
 double e = 0.7623e-2;
 float f = 1.23002398;
 printf("a=%e \nb=%f \nc=%lf \nd=%lE \ne=%lf \nf=%f\n", a, b, c, d, e, f);
 
 return 0;
}


運行結果:
a=3.020000e-01
b=128.100998
c=123.000000
d=1.126400E+05
e=0.007623
f=1.230024

對代碼的說明:
1) %f 和 %lf 默認保留六位小數,不足六位以 0 補齊,超過六位按四捨五入截斷。

2) 將整數賦值給 float 變量時會變成小數。

3) 以指數形式輸出小數時,輸出結果為科學計數法;也就是說,尾數部分的取值為:0 ≤ 尾數 < 10。

4) b 的輸出結果讓人費解,才三位小數,為什麼不能精確輸出,而是輸出一個近似值呢?這和小數在內存中的存儲形式有關,很多簡單的小數壓根不能精確存儲,所以也就不能精確輸出,我們將在下節《小數在內存中是如何存儲的,揭秘諾貝爾獎級別的設計(長篇神文)》中詳細講解。

另外,小數還有一種更加智能的輸出方式,就是使用%g

。%g 會對比小數的十進位形式和指數形式,以最短的方式來輸出小數,讓輸出結果更加簡練。所謂最短,就是輸出結果占用最少的字符。

%g 使用示例:


#include <stdio.h>
#include <stdlib.h>
int main()
{
 float a = 0.00001;
 float b = 30000000;
 float c = 12.84;
 float d = 1.229338455;
 printf("a=%g \nb=%g \nc=%g \nd=%g\n", a, b, c, d);
 
 return 0;
}


運行結果:
a=1e-05
b=3e+07
c=12.84
d=1.22934

對各個小數的分析:

  • a 的十進位形式是 0.00001,占用七個字符的位置,a 的指數形式是 1e-05,占用五個字符的位置,指數形式較短,所以以指數的形式輸出。
  • b 的十進位形式是 30000000,占用八個字符的位置,b 的指數形式是 3e+07,占用五個字符的位置,指數形式較短,所以以指數的形式輸出。
  • c 的十進位形式是 12.84,占用五個字符的位置,c 的指數形式是 1.284e+01,占用九個字符的位置,十進位形式較短,所以以十進位的形式輸出。
  • d 的十進位形式是 1.22934,占用七個字符的位置,d 的指數形式是 1.22934e+00,占用十一個字符的位置,十進位形式較短,所以以十進位的形式輸出。


讀者需要注意的兩點是:

  • %g 默認最多保留六位有效數字,包括整數部分和小數部分;%f 和 %e 默認保留六位小數,只包括小數部分。
  • %g 不會在最後強加 0 來湊夠有效數字的位數,而 %f 和 %e 會在最後強加 0 來湊夠小數部分的位數。


總之,%g 要以最短的方式來輸出小數,並且小數部分表現很自然,不會強加零,比 %f 和 %e 更有彈性,這在大部分情況下是符合用戶習慣的。

除了 %g,還有 %lg、%G、%lG:

  • %g 和 %lg 分別用來輸出 float 類型和 double 類型,並且當以指數形式輸出時,e小寫。
  • %G 和 %lG 也分別用來輸出 float 類型和 double 類型,只是當以指數形式輸出時,E大寫。

數字的後綴

一個數字,是有默認類型的:對於整數,默認是 int 類型;對於小數,默認是 double 類型。

請看下面的例子:


long a = 100;
int b = 294;

float x = 52.55;
double y = 18.6;


100 和 294 這兩個數字默認都是 int 類型的,將 100 賦值給 a,必須先從 int 類型轉換為 long 類型,而將 294 賦值給 b 就不用轉換了。

52.55 和 18.6 這兩個數字默認都是 double 類型的,將 52.55 賦值給 x,必須先從 double 類型轉換為 float 類型,而將 18.6 賦值給 y 就不用轉換了。

如果不想讓數字使用默認的類型,那麼可以給數字加上後綴,手動指明類型:

  • 在整數後面緊跟 l 或者 L(不區分大小寫)表明該數字是 long 類型;
  • 在小數後面緊跟 f 或者 F(不區分大小寫)表明該數字是 float 類型。


請看下面的代碼:


long a = 100l;
int b = 294;
short c = 32L;
 
float x = 52.55f;
double y = 18.6F;
float z = 0.02;


加上後綴,雖然數字的類型變了,但這並不意味著該數字只能賦值給指定的類型,它仍然能夠賦值給其他的類型,只要進行了一下類型轉換就可以了。

對於初學者,很少會用到數字的後綴,加不加往往沒有什麼區別,也不影響實際編程,但是既然學了C語言,還是要知道這個知識點的,萬一看到別人的代碼這麼用了,而你卻不明白怎麼回事,那就尷尬了。

關於數據類型的轉換,我們將在《C語言數據類型轉換》一節中深入探討。

小數和整數相互賦值

在C語言中,整數和小數之間可以相互賦值:

  • 將一個整數賦值給小數類型,在小數點後面加 0 就可以,加幾個都無所謂。
  • 將一個小數賦值給整數類型,就得把小數部分丟掉,只能取整數部分,這會改變數字本來的值。注意是直接丟掉小數部分,而不是按照四捨五入取近似值。


請看下面的代碼:


#include <stdio.h>
int main(){
 float f = 251;
 int w = 19.427;
 int x = 92.78;
 int y = 0.52;
 int z = -87.27;
 
 printf("f = %f, w = %d, x = %d, y = %d, z = %d\n", f, w, x, y, z);

 return 0;
}


運行結果:
f = 251.000000, w = 19, x = 92, y = 0, z = -87

由於將小數賦值給整數類型時會「失真」,所以編譯器一般會給出警告,讓大家引起注意。

關鍵字: