Java 基本類型轉換規則:byte → short → int → long → float → double、char → int 為擴寬轉換(自動),逆向為窄化轉換(需強制)。教科書常說擴寬不丟失精度,但 int→float、long→float、long→double 是例外。
int i = 2000000000;
int num = 0;
for (float f = i; f < i + 50; f++) {
num++;
}
System.out.println(num); // 輸出 0,而非預期的 50
為什麼迴圈一次都沒跑?進一步測試:
int i = 2000000000;
float f1 = i;
float f2 = i + 50;
System.out.println(f1 == f2); // 輸出 true!
int 佔 32 位,符號位 1 位,實際精度 31 位float 佔 32 位:1 位符號、8 位指數、23 位尾數(含隱含位共 24 位精度)2000000000 需 31 位精確表示,轉 float 時只保留高 24 位,低 7 位捨棄2000000000 與 2000000050 低 7 位不同,但高 24 位相同 → 轉換後數值相等| 轉換方向 | 精度風險 | 說明 |
|---|---|---|
| int → float | 高 | int 31 位有效數字 > float 24 位精度 |
| long → float | 極高 | long 63 位有效數字 ≫ float 24 位精度 |
| long → double | 中 | long 63 位 > double 53 位精度(52 位尾數+隱含位) |
i += 1 ≠ i = i + 1byte b = 5;
b += 1; // 編譯通過:隱式將結果轉為 byte
b = b + 1; // 編譯失敗:int 無法自動賦值給 byte
複合賦值(+=、-=、*= 等)會自動將運算結果強制轉型為左操作數類型,這在不知不覺中發生。
byte b = 120;
b += 20; // 140 超出 byte 範圍(-128~127)
System.out.println(b); // 輸出 -116(140 的補碼表示)
int/long 或 BigDecimalMath.abs(a - b) < 1e-5long→float/double、int→float 隱式轉換場景Java 類型系統設計精妙,但「擴寬不丟失精度」並非絕對真理。理解 IEEE 754 存儲規則、掌握隱式轉型行為,是寫出健壯數值計算代碼的關鍵。下次當你看到 float f = largeInt; 時,請三思:這真的是你想要的精度嗎?