float和double有什么區別?


float和double在游戲行業肯定是用的很多的,雖然這是個很基礎的問題,但是面試時被問到還是感覺說的不是很好。
所以還是總結一下:

float 單精度浮點數在機內占 4 個字節,用 32 位二進制描述。

double 雙精度浮點數在機內占 8 個字節,用 64 位二進制描述。

浮點數在機內用指數型式表示,分解為:數符,尾數,指數符,指數四部分。

數符占 1 位二進制,表示數的正負。

指數符占 1 位二進制,表示指數的正負。

尾數表示浮點數有效數字,0.xxxxxxx, 但不存開頭的 0 和點。

指數存指數的有效數字。

指數占多少位,尾數占多少位,由計算機系統決定。

可能是數符加尾數占 24 位,指數符加指數占 8 位 -- float。

數符加尾數占 48 位,指數符加指數占 16 位 -- double。

知道了這四部分的占位,按二進制估計大小范圍,再換算為十進制,就是你想知道的數值范圍。

對編程人員來說,double 和 float 的區別是 double 精度高,有效數字 16 位,float 精度 7 位。但 double 消耗內存是 float 的兩倍,double 的運算速度比 float 慢得多,
C 語言中數學函數名稱 double 和 float 不同,不要寫錯,能用單精度時不要用雙精度(以省內存,加快運算速度)。

簡單來說,Float 為單精度,內存中占 4 個字節,有效數位是 7 位(因為有正負,所以不是8位),在我的電腦且 VC++6.0 平台中默認顯示是6位有效數字;double為 雙精度,占 8 個字節,有效數位是 16 位,但在我的電腦且 VC++6.0 平台中默認顯示同樣是 6 位有效數字

例子:在 C 和 C++ 中,如下賦值語句:

float a=0.1; 

編譯器報錯:warning C4305: 'initializing' : truncation from 'const double ' to 'float '

原因: 在 C/C++ 中(也不知道是不是就在 VC++ 中這樣),上述語句等號右邊 0.1,我們以為它是個 float,但是編譯器卻把它認為是個 double(因為小數默認是 double),所以要報這個 warning,一般改成 0.1f 就沒事了。

本人通常的做法,經常使用 double,而不喜歡使用 float。

C 語言和 C# 語言中,對於浮點類型的數據采用單精度類型 float 和雙精度類型 double 來存儲,float 數據占用 32bit, double 數據占用 64bit,我們在聲明一個變量 float f= 2.25f 的時候,是如何分配內存的呢?如果胡亂分配,那世界豈不是亂套了么,其實不論是 float 還是 double 在存儲方式上都是遵從 IEEE 的規范 的,float 遵從的是 IEEE R32.24 ,而 double 遵從的是 R64.53。

無論是單精度還是雙精度在存儲中都分為三個部分:

符號位(Sign):0 代表正,1 代表為負。
指數位(Exponent):用於存儲科學計數法中的指數數據,並且采用移位存儲。
尾數部分(Mantissa):尾數部分。

特別注意:

當你不聲明的時候,默認小數都用double來表示,所以如果要用float的話,則應該在其后加上f

例如:float a=1.3;

則會提示不能將double轉化成float 這成為窄型轉化

如果要用float來修飾的話,則應該使用float a=1.3f

注意float是8位有效數字,第7位數字將會產生四舍五入

所以如果一個float變量 這樣定義: float a=1.32344435; 則第7位將產生四舍五入(5及5以下的都將舍去)

1.兩個在定義時的區別

(1)float型 內存分配4個字節,占32位,范圍從10-38到1038 和 -1038到-10-38

例float x=123.456f,y=2e20f; 注意float型定義的數據末尾必須有"f"或"F",為了和double區別

(2)double型 內存分配8個字節,范圍從10-308到10308 和 -10-308到-10-308
例:double x=1234567.98,y=8980.09d; 末尾可以有"d"也可以不寫

2、特別需要注意的是兩個浮點數的算術運算

直接使用 +,-,*,%運算符的問題

 public class Test{
        public static void main(String args[]){
        System.out.println(0.05+0.01);
        System.out.println(1.0-0.42);
        System.out.println(4.015*100);
        System.out.println(123.3/100);
        }
    }

結果:

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

原因:

首先得從計算機本身去討論這個問題。我們知道,計算機並不能識別除了二進制數據以外的任何數據。無論我們使用何種編程語言,在何種編譯環境下工作,都要先把源程序翻譯成二進制的機器碼后才能被計算機識別。
以上面提到的情況為例,我們源程序里的2.4是十進制的,計算機不能直接識別,要先編譯成二進制。但問題來了,2.4的二進制表示並非是精確的2.4,反而最為接近的二進制表示是2.3999999999999999。原因在於
浮點數由兩部分組成:指數和尾數,這點如果知道怎樣進行浮點數的二進制與十進制轉換,應該是不難理解的。如果在這個轉換的過程中,浮點數參與了計算,那么轉換的過程就會變得不可預知,並且變得不可逆。
我們有理由相信,就是在這個過程中,發生了精度的丟失。而至於為什么有些浮點計算會得到准確的結果,應該也是碰巧那個計算的二進制與十進制之間能夠准確轉換。而當輸出單個浮點型數據的時候,可以正確輸出,如

double d = 2.4;
System.out.println(d);

輸出的是2.4,而不是2.3999999999999999。也就是說,不進行浮點計算的時候,在十進制里浮點數能正確顯示。
這更印證了我以上的想法,即如果浮點數參與了計算,那么浮點數二進制與十進制間的轉換過程就會變得不可預知,並且變得不可逆。

事實上,浮點數並不適合用於精確計算,而適合進行科學計算。這里有一個小知識:既然float和double型用來表示帶有小數點的數,那為什么我們不稱它們為“小數”或者“實數”,要叫浮點數呢?因為這些數都以科學計數法的形式存儲。
當一個數如50.534,轉換成科學計數法的形式為5.053e1,它的小數點移動到了一個新的位置(即浮動了)。可見,浮點數本來就是用於科學計算的,用來進行精確計算實在太不合適了。

參考:
https://my.oschina.net/zd370982/blog/724265
https://www.jb51.net/article/159043.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM