java.lang.Math 提供豐富的數學運算靜態方法,配合 java.util.Random 及 Java 7+ ThreadLocalRandom,可高效解決數值計算、隨機生成等常見需求。本文整理核心 API、陷阱與最佳實踐。
| 方法 | 功能 | 範例 | 結果 | 備註 |
|---|---|---|---|---|
| abs(x) | 絕對值 | Math.abs(-3.14) | 3.14 | 重載支援 int/long/float/double |
| max/min(a,b) | 最大/最小值 | Math.max(3,5) | 5 | |
| ceil(x) | 向上取整(≥x 最小整數) | Math.ceil(2.3) | 3.0 | 返回 double |
| floor(x) | 向下取整(≤x 最大整數) | Math.floor(-1.8) | -2.0 | 負數注意方向 |
| round(x) | 四捨五入 | Math.round(2.5) | 3 | float→int, double→long |
| sqrt(x) | 平方根 | Math.sqrt(9) | 3.0 | x<0 返回 NaN |
| cbrt(x) | 立方根 | Math.cbrt(27) | 3.0 | Java 1.5+ |
| pow(a,b) | a 的 b 次方 | Math.pow(2,10) | 1024.0 | |
| exp(x) | e^x | Math.exp(1) | 2.718... | |
| log(x) | 自然對數 ln(x) | Math.log(Math.E) | 1.0 | x≤0 返回 NaN |
| log10(x) | 以 10 為底對數 | Math.log10(100) | 2.0 | Java 1.5+ |
| random() | [0.0, 1.0) 偽隨機 | Math.random() | 0.732... | 內部用共享 Random 實例 |
| signum(x) | 符號函數 | Math.signum(-5) | -1.0 | 返回 -1/0/1 |
| ulp(x) | 單位在最後一位 | Math.ulp(1.0) | 1.19e-7 | 浮點精度分析用 |
round(float) → int,round(double) → long,切勿直接賦值給 int 變數導致精度損失。(int)Math.floor(x)。Math.floorMod(-3, 2) = 1(Java 8+),與 % 行為不同。Math.pow(10, 20) 產生 double 近似值,精確整數運算請用 BigInteger。NaN 運算結果皆為 NaN,判斷用 Double.isNaN()。Random rand = new Random(); // 種子預設 System.nanoTime()
rand.nextInt(); // 全範圍 int
rand.nextInt(100); // [0, 100)
rand.nextLong(); // 全範圍 long
rand.nextDouble(); // [0.0, 1.0)
rand.nextFloat(); // [0.0, 1.0f)
rand.nextBoolean(); // true/false
rand.nextGaussian(); // 正態分佈 μ=0, σ=1
byte[] bytes = new byte[16];
rand.nextBytes(bytes); // 填充隨機位元組
Random rand = new Random(12345L); // 固定種子 → 固定序列
// 生產環境勿用固定種子,否則隨機性完全可預測
// 無需共享實例,每執行緒獨立,無競爭
int val = ThreadLocalRandom.current().nextInt(4, 64); // [4, 64)
long id = ThreadLocalRandom.current().nextLong(1000, 10000);
double rate = ThreadLocalRandom.current().nextDouble(0.0, 1.0);
優勢:避免 Random 共享實例的 CAS 競爭,多執行緒環境下吞吐量顯著提升。
SecureRandom sr = new SecureRandom();
byte[] token = new byte[32];
sr.nextBytes(token); // 產生加密安全的隨機位元組
// 適用:Session ID、API Token、加密金鑰、OAuth state
注意:SecureRandom 初始化較慢(熵收集),高頻調用建議複用實例或使用 ThreadLocal 緩存。
public final class MathUtils {
private MathUtils() {}
/** 產生 [min, max] 區間隨機整數(含邊界) */
public static int randomInt(int min, int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
/** 產生指定長度數字驗證碼 */
public static String numericCode(int length) {
ThreadLocalRandom r = ThreadLocalRandom.current();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) sb.append(r.nextInt(10));
return sb.toString();
}
/** 保留 n 位小數四捨五入(基於 BigDecimal 避免浮點誤差) */
public static double round(double val, int scale) {
return BigDecimal.valueOf(val)
.setScale(scale, RoundingMode.HALF_UP)
.doubleValue();
}
}
Math.random() 或 new Random()。double + Math.round。new Random(seed)。