![](/img/trans.png)
[英]Java - Decimal Format Precision lost when returning a Float or Decimal
[英]java - float precision when output in console
float x = 0.98123452f;
System.out.println(x); //it prints out 0.9812345
float x = 0.98123453f;
System.out.println(x); //it prints out 0.98123455
我不知道為什么第二個輸出是0.98123455而不是0.9812345。 浮點數的精度不是7個十進制數字嗎?
要查看浮點數的確切值,可以使用BigDecimal:
float x = 0.98123452f; System.out.println(new BigDecimal(x));
輸出:
0.981234490871429443359375
因此,從技術上講,該浮動:
float x = 0.981234490871429443359375f; System.out.println(new BigDecimal(x)); //prints 0.981234490871429443359375
具有24位精度(顯然是挑剔的)...
忘記上面的內容:BigDecimal只有一個double構造函數,因此進行了強制轉換為double,並且上面的邏輯存在缺陷。
底線:並非所有數字都可以表示為浮點數,一個浮點數與下一個浮點數之間的距離取決於數字的大小而變化。
IEEE 754的浮點表示形式
0.98123453
是32位(符號,exp,尾數):
0 01111110 11110110011001000110000
這是:
0.9812345504760742
以雙精度,然后轉換回浮點十進制表示形式:
0.98123455
分配給單精度(浮點數)的位數為32,而雙精度則為64位。 還要注意,經常建議使用BigDecimal
,它將您的數字存儲為字符串,而不是IEEE754格式。 當需要對數字進行運算時,它將進行轉換,並且雖然精度更高,但速度非常慢。
編輯。 為了闡明為什么打印0.98123455,我們需要觀察它是數字0.98123453的最接近的單精度表示形式:
00111111011110110011001000101111 = 0.9812345 (sp) = 0.9812344908714294 (dp)
00111111011110110011001000110000 = 0.98123455 (sp) = 0.9812345504760742 (dp)
00111111011110110011001000110001 = 0.9812346 (sp) = 0.981234610080719 (dp)
sp =單精度,dp =雙精度
該清單是針對數字附近的[-1,+ 1]二進制范圍的,您可以看到0.98123453
最接近尾數的10000
后綴,而0.98123452
最接近后綴01111
。
浮點數的精度不是7個十進制數字嗎?
否。它是23位二進制數字。 因此,可以用23位表示的十進制數字的最小數目為6。這不僅僅是在此處的其他答案中所述的“保證”,它是由log10(2 ^ 23)= 6.92369引起的數學重言式。
Java中浮點數的默認輸出格式是僅打印足夠的數字,以便轉換回浮點類型時會產生原始值。
您的代碼中發生的詳細信息是:
0.98123452f
轉換為float
值0.981234490871429443359375。 float
值是0.981234490871429443359375。 但是,將“ 0.981234”轉換為float
將產生0.981234014034271240234375,因此需要“ 5”。 0.98123453f
轉換為float
值0.98123455047607421875。 有趣的結果是,如果將float
值分配給double
對象,然后打印該double
值,則即使打印的值完全相同,也通常會比打印float
值顯示更多的數字。 因為double
格式比float
格式更好(更精確),所以在為float
打印的值(例如0.9812345)和實際值(0.981234490871429443359375)之間可能會有很多double
值。 因此,需要更多的數字來區分該值。
不, float
只有六位數的十進制精度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.