1.四捨五入實數
正如我們已經討論過的,當一個實數被分配給一個int
變量時,它總是被四捨五入到最接近的更小的整數——小數部分被簡單地丟棄。
但是很容易想像這樣一種情況,當一個小數需要在任一方向上四捨五入到最接近的整數,甚至四捨五入。在這種情況下你會怎麼做?
對於這種情況和許多類似的情況,Java 有類Math
,它有round()
、ceil()
和floor()
方法。
Math.round()
方法
該Math.round()
方法將數字四捨五入為最接近的整數:
long x = Math.round(real_number)
但這裡還有另一個細微差別:此方法返回一個long
整數(不是int
)。因為實數可能非常大,Java 的創建者決定使用 Java 最大的可用整數類型:long
.
因此,如果程序員想要將結果分配給一個int
變量,那麼她必須明確地向編譯器表明她接受可能的數據丟失(如果結果數字不適合某種類型int
)。
int x = (int) Math.round(real_number)
例子:
陳述 | 結果 |
---|---|
|
|
|
|
|
|
Math.ceil()
方法
該Math.ceil()
方法將數字四捨五入為整數。以下是示例:
陳述 | 結果 |
---|---|
|
|
|
|
|
|
Math.floor()
方法
該Math.floor()
方法將數字向下舍入為整數。以下是示例:
陳述 | 結果 |
---|---|
|
|
|
|
|
|
當然,當將數字向下舍入為整數時,簡單地使用類型轉換運算符會更容易:(int)
陳述 | 結果 |
---|---|
|
|
如果您覺得很難記住這些名字,簡短的英語課會有所幫助:
Math
意味著數學Round
表示圓形Ceiling
意味著天花板Floor
意味著地板
2. 浮點數的結構
該類型可以存儲從到double
範圍內的值。這種巨大的值範圍(與類型相比)是由於類型(以及)具有與整數類型完全不同的內部結構這一事實。在內部,該類型將其值編碼為兩個數字:第一個稱為尾數,第二個稱為指數。-1.7*10308
+1.7*10308
int
double
float
double
假設我們有數字123456789
並將其存儲在一個double
變量中。當我們這樣做時,數字被轉換為,並且在內部類型存儲兩個數字 —和。尾數(“數字的重要部分”或尾數)以紅色突出顯示,而指數以藍色突出顯示。1.23456789*108
double
23456789
8
這種方法可以存儲非常大的數字和非常小的數字。但是由於數字的表示限制為 8 個字節(64 位),並且其中一些位用於存儲指數(以及尾數的符號和指數的符號),因此可用於表示尾數的最大位數是15 歲。
這是對實數結構的非常簡化的描述。
3. 處理實數時精度損失
使用實數時,請始終牢記實數 並不精確。從十進制轉換為二進制時,可能總是會出現舍入錯誤和轉換錯誤。此外,最常見的錯誤來源是在完全不同的尺度上添加/減去數字時的精度損失。
最後一個事實對於新手程序員來說有點令人興奮。
如果我們從 中減去,我們得到。1/109
109
109
在完全不同的尺度上減去數字 | 解釋 |
---|---|
|
第二個數字非常小,這將導致其有效數字(以灰色突出顯示)被忽略。15位有效數字以橙色突出顯示。 |
我們能說什麼,編程與數學不同。
4.比較實數時的陷阱
另一個危險在於等待程序員比較實數。它在處理實數時出現,因為捨入誤差會累積。結果是,在某些情況下,預期實數相等,但事實並非如此。反之亦然:數字應該不同,但它們是相等的。
例子:
陳述 | 解釋 |
---|---|
|
變量的值a 將是1000000000.0 變量的值 c 將是1000000000.0 (變量中的數字 b 過小) |
在上面的例子中,a
andc
不應該相等,但它們是。
或者我們再舉一個例子:
陳述 | 解釋 |
---|---|
|
變量的值a 將是1.0 變量的值 b 將是1.0 |
5. 一個有趣的事實strictfp
Java有一個特殊的關鍵字strictfp
(strict floating point ),這是其他編程語言所沒有的。你知道你為什麼需要它嗎?它會降低浮點數運算的準確性。這是它是如何形成的故事:
GO TO FULL VERSION