1. 程式人生 > 程式設計 >java 數學計算的具體使用

java 數學計算的具體使用

java.lang.Math 庫提供了常用的數學計算工具

常量

final double E = 2.7182818284590452354;         // 自然對數底數
final double PI = 3.14159265358979323846;        // 圓周率
final double DEGREES_TO_RADIANS = 0.017453292519943295; // 角度轉弧度
final double RADIANS_TO_DEGREES = 57.29577951308232;  // 弧度轉角度

取整

  • abs(x): 絕對值
  • floor(x): 向下取整
  • ceil(x): 向上取整
  • round(x): 四捨五入,如果有兩個(x.5),返回較大的那個數
  • rint(x): 最接近的整數,如果有兩個(x.5),返回偶數
  • floorDiv(x,y): 向下取整除法
  • floorMod(x,y): java 預設的取摸 % 得到的結果和 x 的符號相同,floorMod 和 y 的符號相同
double delta = 0.0000001;
assertEquals(Math.abs(-6),6);
assertEquals(Math.floor(-6.2),-7,delta); // 向下取整
assertEquals(Math.floor(6.2),6,delta);
assertEquals(Math.floor(6.8),delta);
assertEquals(Math.ceil(-6.2),-6,delta);  // 向上取整
assertEquals(Math.ceil(6.2),7,delta);
assertEquals(Math.ceil(6.8),delta);
assertEquals(Math.round(-6.2),delta); // 四捨五入
assertEquals(Math.round(6.2),delta);
assertEquals(Math.round(6.8),delta);
assertEquals(Math.round(-6.5),delta);
assertEquals(Math.round(6.5),delta);
assertEquals(Math.rint(-6.2),delta); // 最接近整數,如果存在兩個,返回偶數
assertEquals(Math.rint(6.2),delta);
assertEquals(Math.rint(6.8),delta);
assertEquals(Math.rint(-6.5),delta);
assertEquals(Math.rint(6.5),delta);

assertEquals(Math.floorDiv(7,3),2);
assertEquals(Math.floorDiv(-7,-3);
assertEquals(Math.floorMod(7,1);
assertEquals(Math.floorMod(-7,-3),-1);
assertEquals(Math.floorMod(-7,2);
assertEquals(-7 % -3,-1);
assertEquals(-7 % 3,-1);

三角函式

assertEquals(Math.sin(Math.PI / 2),1.0,delta);
assertEquals(Math.cos(Math.PI),-1,delta);
assertEquals(Math.tan(Math.PI / 4),delta);
assertEquals(Math.asin(1),Math.PI / 2,delta);
assertEquals(Math.acos(-1),Math.PI,delta);
assertEquals(Math.atan(1),Math.PI / 4,delta);

指數對數

  • pow(x,y): x^y,x 的 y 次方
  • sqrt(x): √x,x 的平方根
  • cbrt(x): 三次方根
  • hypot(x,y): √(x² + y²)
  • exp(x): e ^ x
  • expm1(x): e ^ x - 1
  • log(x): ln(x)
  • log10: lg(x)
  • log1p(x): ln(1+x)
assertEquals(Math.pow(3,2),9,delta);
assertEquals(Math.pow(2,8,delta);
assertEquals(Math.sqrt(4),2,delta);
assertEquals(Math.cbrt(27),3,delta);
assertEquals(Math.hypot(3,4),5,delta);  // √(x² + y²)

assertEquals(Math.exp(2.5),Math.pow(Math.E,2.5),delta); // e ^ x
assertEquals(Math.expm1(2),Math.exp(2) - 1,delta);  // e ^ x - 1
assertEquals(Math.log(Math.exp(1.5)),1.5,delta); // ln(x)
assertEquals(Math.log10(1000),delta);      // lg(x)
assertEquals(Math.log1p(Math.E - 1),1,delta);   // ln(1 + x)

雙曲函式

  • sinh(x): (e ^ x - e ^ -x) / 2
  • cosh(x): (e ^ x + e ^ -x) / 2
  • tanh(x): sinh(x) / cosh(x)
assertEquals(Math.sinh(2),(Math.exp(2) - Math.exp(-2)) / 2,delta);  // sinh(x) = (e ^ x - e ^ -x) / 2
assertEquals(Math.cosh(2),(Math.exp(2) + Math.exp(-2)) / 2,delta);  // cosh(x) = (e ^ x + e ^ -x) / 2
assertEquals(Math.tanh(2),Math.sinh(2) / Math.cosh(2),delta);     // tanh(x) = sinh(x) / cosh(x)

精確計算

普通的數值計算在溢位時是沒有感知的,比如 Long.MAX_VALUE + 1 將得到結果 Long.MIN_VALUE,為了解決這種不合理,Math 提供了一些輔助函式,在結果溢位時將丟擲異常

  • addExact(x,y): 加法
  • multiplyExact(x,y): 乘法
  • decrementExact(x,y): 遞減
  • incrementExact(x,y): 遞增
  • negateExact(x,y): 相反數
  • multiplyFull(x,y): 接受兩個 int 返回一個 long,防止溢位
  • multiplyHigh(x,y): 返回兩個 long 乘積的高 64 位
assertEquals(Long.MAX_VALUE + 1,Long.MIN_VALUE);                    // 溢位
assertThrows(ArithmeticException.class,() -> Math.addExact(Long.MAX_VALUE,1));    // 加法溢位拋異常
assertThrows(ArithmeticException.class,() -> Math.multiplyExact(Long.MAX_VALUE,2));  // 乘法
assertThrows(ArithmeticException.class,() -> Math.decrementExact(Long.MIN_VALUE));   // 遞減
assertThrows(ArithmeticException.class,() -> Math.incrementExact(Long.MAX_VALUE));   // 遞增
assertThrows(ArithmeticException.class,() -> Math.negateExact(Long.MIN_VALUE));    // 相反數
assertEquals(Math.addExact(1,3);
assertEquals(Math.multiplyExact(2,6);
assertEquals(Math.incrementExact(6),7);
assertEquals(Math.decrementExact(6),5);
assertEquals(Math.negateExact(-6),6);

assertEquals(Math.multiplyFull(1,2);  // 接受兩個 int 返回一個 long,防止溢位
assertEquals(Math.multiplyHigh(1,0);  // 返回兩個 long 乘積的高 64 位

浮點數

任意兩個浮點數之間都有無數個浮點數,因此大部分浮點數是無法表示的,只能選取一個最接近的,java 提供了一些介面來獲取能表示的浮點數

System.out.println(Math.nextUp(1.1));  // 下一個浮點數
System.out.println(Math.nextDown(1.1)); // 上一個浮點數
System.out.println(Math.nextAfter(1.1,Double.POSITIVE_INFINITY));  // 下一個浮點數
System.out.println(Math.nextAfter(1.1,Double.NEGATIVE_INFINITY));  // 上一個浮點數

隨機數

math 庫隨機數

System.out.println(Math.random());     // 0 ~ 1 之間的隨機數

java.lang.Random

Random 類提供了更豐富的隨機方法,可以返回各種不同型別的隨機數

Random r = new Random();
System.out.println(r.nextInt());
System.out.println(r.nextLong());
System.out.println(r.nextFloat());
System.out.println(r.nextDouble());

Random 還提供了流式 api

Random r = new Random();
List<Integer> li = r.ints().limit(10).boxed().map((x) -> Math.abs(x % 100)).collect(Collectors.toList());
System.out.println(li);

java.util.Random 是執行緒安全的,但是,跨執行緒的同時使用 java.util.Random 例項可能會遇到爭用,從而導致效能下降。在多執行緒設計中考慮使用java.util.concurrent.ThreadLocalRandom 代替 java.util.Random,ThreadLocalRandom 和 Random 擁有一致的介面

連結

Math 測試程式碼: https://github.com/hatlonely/hellojava/blob/master/src/test/java/util/MathTest.java
隨機數測試程式碼: https://github.com/hatlonely/hellojava/blob/master/src/test/java/util/RandomTest.java

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。