[英]Double to Int without lossy precision
以下聲明給出了編譯時錯誤“錯誤:(19,13)java:不兼容類型:可能從double轉換為int的有損轉換”
int i1 = 10.0;
// Error:(19, 14) java: incompatible types: possible lossy conversion from double to int
問題1
我理解錯誤,但編譯器可以不推斷 - 在這種特殊情況下 - 不會有精度損失?
問題2
如果我顯式地將double轉換為int
然后它編譯很好(甚至不是警告),即使我在這個例子中肯定會失去精度
int i2 = (int)9999999999999.999999999;
如果我無法編譯第一種情況 - 沒有發生丟失 - 那么為什么第二個顯式轉換示例甚至不會生成編譯器警告?
理論上,編譯器可以推斷#1中的具體示例實際上不會根據文字的值松散精度,但正如您所見 - 它沒有。
顯式轉換信號通知編譯器您知道處理它的情況,因此代碼實際編譯。 但是,大多數IDE都可以配置為在這種情況下發出警告。
將double
值賦值給int
變量需要縮小轉換 ,即使該值是編譯時常量,因此需要顯式轉換。
不同之處在於int
(或short
或char
)恆定值可以被分配給一個byte
, short
,或char
可變而不鑄造,如果常數實際上在各變量值范圍配合,以Java語言規范明確地記載,部分5.2。 作業上下文 :
賦值上下文允許將表達式的值賦值(第15.26節 )給變量; 必須將表達式的類型轉換為變量的類型。
賦值上下文允許使用以下之一:
身份轉換( §5.1.1 )
擴展的原始轉換(第5.1.2節 )
擴大參考轉換(第5.1.5節 )
一個拳擊轉換( §5.1.7 ),可選地后跟一個加寬的引用轉換
一個拆箱轉換(第5.1.8節 ),可選地后跟一個加寬的基元轉換。
如果在應用上面列出的轉換后,結果類型是原始類型( §4.8 ),則可以應用未經檢查的轉換(第5.1.9節 )。
此外, 如果表達式是
byte
,short
,char
或int
類型的常量表達式(第15.28節 ) :
如果變量的類型是
byte
,short
或char
,則可以使用縮小的基元轉換,並且常量表達式的值可以在變量的類型中表示 。如果變量的類型是:則可以使用縮小的基元轉換,然后進行裝箱轉換:
Byte
和常量表達式的值可在類型byte
表示。
Short
和常量表達式的值可以在short
類型中表示。
Character
和常量表達式的值可在char
類型中表示。
回答問題1
根據編譯器的精度損失,因為編譯器只看到左邊有一個int變量,右邊有一個double值。 編譯器不是那么聰明,以至於在轉換為int時10.0
不會失去精度。
理論上可以構建編譯器以允許編譯該語句,但這樣做沒有實際好處。 幾乎沒有人寫int x = 10.0
。
回答問題2
實際上,精度有所下降,但為什么編譯器不抱怨? 因為你使用了演員。 你寫了(int)
。 這是您向編譯器顯示您知道自己在做什么。 通過編寫演員表,你告訴它你知道可能會失去精確度。
有趣的問題
理論上這可能是有可能的, javac
在做的時候不會抱怨:
short s = 12;
即使這里的12
是int
類型的編譯時常量,也可以推斷出沒有精度丟失。 我想這是編譯器團隊認為最合適的。
好吧當你cast
是一個不同的故事時,就像說“相信我,我知道我在做什么”,即使你精確度不高。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.