Java 数学工具类 Math

目录

一、核心字段:自然常数与圆周率

[1. Math.E](#1. Math.E)

[2. Math.PI](#2. Math.PI)

二、基础运算方法

[1.绝对值计算:abs 系列方法](#1.绝对值计算:abs 系列方法)

2.加减乘除与精确运算

[1. 加法:addExact](#1. 加法:addExact)

[2. 减法:subtractExact](#2. 减法:subtractExact)

[3. 乘法](#3. 乘法)

4.取整与舍入

[1. ceil(double a):向上取整](#1. ceil(double a):向上取整)

[2. floor(double a):向下取整](#2. floor(double a):向下取整)

[3. rint(double a):四舍五入到最近整数(返回 double)](#3. rint(double a):四舍五入到最近整数(返回 double))

[4. round:四舍五入到整数(返回 int 或 long)](#4. round:四舍五入到整数(返回 int 或 long))

3.三角函数与双曲线函数

1.基本三角函数:sin、cos、tan

2.角度与弧度转换

3.反三角函数:asin、acos、atan、atan2

4.双曲线函数:sinh、cosh、tanh

4.指数与对数运算

1.指数运算:exp、expm1、pow

[1.1. exp(double a):计算自然指数 e^a](#1.1. exp(double a):计算自然指数 e^a)

[1.2. expm1(double x):计算 e^x - 1](#1.2. expm1(double x):计算 e^x - 1)

[1.3. pow(double a, double b):计算 a^b](#1.3. pow(double a, double b):计算 a^b)

2.对数运算:log、log10、log1p

[2.1、log(double a):计算自然对数 ln(a)](#2.1、log(double a):计算自然对数 ln(a))

[2.2、log10(double a):计算以 10 为底的对数 log10(a)](#2.2、log10(double a):计算以 10 为底的对数 log10(a))

[2.3、log1p(double x):计算 ln(1 + x)](#2.3、log1p(double x):计算 ln(1 + x))

三、其他实用方法

1、平方根与立方根:sqrt、cbrt

2、随机数生成:random

[3、符号与 ulp 操作](#3、符号与 ulp 操作)

[1. 衡量浮点数的 "接近程度"(替代直接相等判断)](#1. 衡量浮点数的 “接近程度”(替代直接相等判断))

[2. 分析数值算法的精度](#2. 分析数值算法的精度)

[3. 调试浮点计算异常](#3. 调试浮点计算异常)

四、资料来源


在 Java 编程中,数值计算是一项基础且核心的任务。无论是简单的加减乘除,还是复杂的三角函数、指数运算,Java 标准库都为我们提供了一个强大的工具 ------java.lang.Math 类。这个类包含了大量用于执行基本数值运算的静态方法,涵盖了从简单的绝对值计算到复杂的浮点运算等多个方面。

一、核心字段:自然常数与圆周率

Math类定义了两个常用的数学常数,它们是程序中进行科学计算的基础:

1. Math.E

表示自然对数的底数 e (约等于 ++2.71828++ ),是一个 double 类型的常量。

java 复制代码
public class MathConstants {
    public static void main(String[] args) {
        System.out.println("圆周率 π: " + Math.PI); // 输出:3.141592653589793
        // 示例:计算半径为 5 的圆的面积
        double radius = 5;
        double area = Math.PI * radius * radius;
        System.out.println("圆的面积: " + area); // 输出:78.53981633974483
    }
}

2. Math.PI

表示圆周率**π**(约等于 3.14159),同样是 **double**类型的常量,常用于几何计算。

java 复制代码
public class MathConstants {
    public static void main(String[] args) {
        System.out.println("圆周率 π: " + Math.PI); // 输出:3.141592653589793
        // 示例:计算半径为 5 的圆的面积
        double radius = 5;
        double area = Math.PI * radius * radius;
        System.out.println("圆的面积: " + area); // 输出:78.53981633974483
    }
}

二、基础运算方法

1.绝对值计算:**abs**系列方法

**abs**方法用于计算各种数值类型的绝对值,支持 intlongfloatdouble 四种类型:

方法签名 功能描述
static int abs(int a) 返回 int 类型的绝对值
static long abs(long a) 返回 long 类型的绝对值
static float abs(float a) 返回 float 类型的绝对值
static double abs(double a) 返回 double 类型的绝对值

示例代码

java 复制代码
public class MathAbsExample {
    public static void main(String[] args) {
        int intNum = -10;
        long longNum = -10000000000L;
        float floatNum = -3.14f;
        double doubleNum = -2.71828;

        System.out.println("int 绝对值: " + Math.abs(intNum)); // 输出:10
        System.out.println("long 绝对值: " + Math.abs(longNum)); // 输出:10000000000
        System.out.println("float 绝对值: " + Math.abs(floatNum)); // 输出:3.14
        System.out.println("double 绝对值: " + Math.abs(doubleNum)); // 输出:2.71828
    }
}

注意 :对于 ++int++类型,++Integer.MIN_VALUE++ (-2147483648)的绝对值是无法用 int 表示的(因为最大值为 2147483647),此时Math.abs(Integer.MIN_VALUE)** 会返回其本身(++仍为负数++ )。若需检测这种溢出情况,可使用 ++absExact++ 方法:

java 复制代码
public class MathAbsExactExample {
    public static void main(String[] args) {
        try {
            int minInt = Integer.MIN_VALUE;
            System.out.println(Math.absExact(minInt)); // 抛出 ArithmeticException
        } catch (ArithmeticException e) {
            System.out.println("错误:绝对值溢出!" + e.getMessage());
        }
    }
}

2.加减乘除与精确运算

Math 类提供了普通的算术运算支持,同时为了应对溢出问题,引入了一系列带「Exact」后缀的方法,当运算结果溢出时会抛出***ArithmeticException***。

1. 加法:addExact

java 复制代码
public class MathAddExactExample {
    public static void main(String[] args) {
        // 正常情况
        int a = 1000000;
        int b = 2000000;
        System.out.println(Math.addExact(a, b)); // 输出:3000000

        // 溢出情况
        try {
            int maxInt = Integer.MAX_VALUE;
            System.out.println(Math.addExact(maxInt, 1)); // 抛出异常
        } catch (ArithmeticException e) {
            System.out.println("加法溢出:" + e.getMessage());
        }
    }
}

2. 减法:subtractExact

java 复制代码
public class MathSubtractExactExample {
    public static void main(String[] args) {
        long x = 5000000000L;
        long y = 3000000000L;
        System.out.println(Math.subtractExact(x, y)); // 输出:2000000000

        try {
            long minLong = Long.MIN_VALUE;
            System.out.println(Math.subtractExact(minLong, 1)); // 抛出异常
        } catch (ArithmeticException e) {
            System.out.println("减法溢出:" + e.getMessage());
        }
    }
}

3. 乘法

  • multiplyExact:返回乘积,溢出时抛出异常。
  • multiplyFull:返回两个 int 的精确乘积(结果为 long,避免溢出)。
java 复制代码
public class MathMultiplyExample {
    public static void main(String[] args) {
        // multiplyExact
        int m = 123456;
        int n = 789012;
        try {
            System.out.println(Math.multiplyExact(m, n)); // 结果可能溢出 int
        } catch (ArithmeticException e) {
            System.out.println("乘法溢出:" + e.getMessage());
        }

        // multiplyFull:安全计算 int 乘积(返回 long)
        long product = Math.multiplyFull(m, n);
        System.out.println("精确乘积(long):" + product); // 输出:97407519744
    }
}

4.取整与舍入

在处理浮点数时,我们经常需要将其转换为整数,Math 类提供了多种取整方法,适用于不同场景:

1. ceil(double a):向上取整

返回大于或等于参数的最小整数(以 ++double++形式表示)。

java 复制代码
System.out.println(Math.ceil(3.2)); // 输出:4.0
System.out.println(Math.ceil(-3.2)); // 输出:-3.0
System.out.println(Math.ceil(5.0)); // 输出:5.0
2. floor(double a):向下取整

返回小于或等于参数的最大整数(以 ++double++形式表示)。

java 复制代码
System.out.println(Math.floor(3.8)); // 输出:3.0
System.out.println(Math.floor(-3.8)); // 输出:-4.0
System.out.println(Math.floor(5.0)); // 输出:5.0
3. rint(double a):四舍五入到最近整数(返回 double)

若参数距离两个整数等距,则返回偶数。

java 复制代码
System.out.println(Math.rint(3.2)); // 输出:3.0
System.out.println(Math.rint(3.5)); // 输出:4.0(与 3.5 等距,取偶数)
System.out.println(Math.rint(4.5)); // 输出:4.0(与 4.5 等距,取偶数)
4. round:四舍五入到整数(返回 int 或 long)
  • round(float a) :返回int
  • round(double a):返回 long
java 复制代码
System.out.println(Math.round(3.2f)); // 输出:3(int)
System.out.println(Math.round(3.8f)); // 输出:4(int)
System.out.println(Math.round(3.5)); // 输出:4(long)
System.out.println(Math.round(-3.5)); // 输出:-3(long,向正无穷大舍入)

3.三角函数与双曲线函数

Math 类提供了完整的三角函数支持,包括++正弦、余弦、正切及其反函数++,所有角度参数均以弧度为单位。

1.基本三角函数:sincostan

java 复制代码
public class TrigonometryExample {
    public static void main(String[] args) {
        double angle = Math.PI / 6; // 30 度(π/6 弧度)

        // 正弦
        double sinVal = Math.sin(angle);
        System.out.println("sin(30°) = " + sinVal); // 输出:0.5(近似)

        // 余弦
        double cosVal = Math.cos(angle);
        System.out.println("cos(30°) = " + cosVal); // 输出:0.8660254...(√3/2 近似)

        // 正切
        double tanVal = Math.tan(angle);
        System.out.println("tan(30°) = " + tanVal); // 输出:0.57735...(1/√3 近似)
    }
}

2.角度与弧度转换

由于三角函数参数为弧度,可使用 toRadians(度转弧度)和 toDegrees(弧度转度)进行转换:

java 复制代码
double degrees = 45;
double radians = Math.toRadians(degrees);
System.out.println(degrees + "度 = " + radians + "弧度"); // 输出:45.0度 = 0.785398...弧度

double rad = Math.PI / 2;
double deg = Math.toDegrees(rad);
System.out.println(rad + "弧度 = " + deg + "度"); // 输出:1.570796...弧度 = 90.0度

3.反三角函数:asinacosatanatan2

java 复制代码
public class InverseTrigExample {
    public static void main(String[] args) {
        // 反正弦(返回 [-π/2, π/2] 弧度)
        double asin = Math.asin(0.5);
        System.out.println("arcsin(0.5) = " + Math.toDegrees(asin) + "度"); // 输出:30.0度

        // 反余弦(返回 [0, π] 弧度)
        double acos = Math.acos(0.5);
        System.out.println("arccos(0.5) = " + Math.toDegrees(acos) + "度"); // 输出:60.0度

        // 反正切(返回 [-π/2, π/2] 弧度)
        double atan = Math.atan(1);
        System.out.println("arctan(1) = " + Math.toDegrees(atan) + "度"); // 输出:45.0度

        // 坐标反正切(根据 (x,y) 计算角度,返回 [-π, π] 弧度)
        double x = 1;
        double y = 1;
        double atan2 = Math.atan2(y, x);
        System.out.println("atan2(" + y + "," + x + ") = " + Math.toDegrees(atan2) + "度"); // 输出:45.0度
    }
}

4.双曲线函数:sinhcoshtanh

双曲线函数是三角函数的类比,基于指数函数定义:

java 复制代码
public class HyperbolicExample {
    public static void main(String[] args) {
        double x = 1.0;

        // 双曲正弦(sinh(x) = (e^x - e^-x)/2)
        double sinh = Math.sinh(x);
        System.out.println("sinh(1) = " + sinh); // 输出:1.1752011936438014

        // 双曲余弦(cosh(x) = (e^x + e^-x)/2)
        double cosh = Math.cosh(x);
        System.out.println("cosh(1) = " + cosh); // 输出:1.5430806348152437

        // 双曲正切(tanh(x) = sinh(x)/cosh(x))
        double tanh = Math.tanh(x);
        System.out.println("tanh(1) = " + tanh); // 输出:0.7615941559557649
    }
}

4.指数与对数运算

1.指数运算:expexpm1pow

1.1. exp(double a):计算自然指数 e^a
java 复制代码
System.out.println(Math.exp(1)); // 输出:2.718281828459045(e^1)
System.out.println(Math.exp(0)); // 输出:1.0(e^0)
1.2. expm1(double x):计算 e^x - 1

对于接近 0 的 x,该方法比 exp(x) - 1 更精确:

java 复制代码
double x = 0.000001;
System.out.println(Math.exp(x) - 1); // 输出:1.0000005000001665e-06(精度较低)
System.out.println(Math.expm1(x)); // 输出:1.0000005000001667e-06(更精确)
1.3. pow(double a, double b):计算 a^b
java 复制代码
System.out.println(Math.pow(2, 3)); // 输出:8.0(2^3)
System.out.println(Math.pow(10, -2)); // 输出:0.01(10^-2)
System.out.println(Math.pow(4, 0.5)); // 输出:2.0(4的平方根)
System.out.println(Math.pow(0, 0)); // 输出:1.0(特殊规定)

2.对数运算:loglog10log1p

2.1、log(double a):计算自然对数 ln(a)
java 复制代码
System.out.println(Math.log(Math.E)); // 输出:1.0(ln(e))
System.out.println(Math.log(1)); // 输出:0.0(ln(1))
2.2、log10(double a):计算以 10 为底的对数 log10(a)
java 复制代码
System.out.println(Math.log10(100)); // 输出:2.0(log10(100))
System.out.println(Math.log10(0.1)); // 输出:-1.0(log10(0.1))
2.3、log1p(double x):计算 ln(1 + x)

对于接近 0 的 x,比 log(1 + x) 更精确:

java 复制代码
double x = 0.000001;
System.out.println(Math.log(1 + x)); // 输出:9.999995000003333e-07(精度较低)
System.out.println(Math.log1p(x)); // 输出:9.999995000001666e-07(更精确)

三、其他实用方法

1、平方根与立方根:sqrtcbrt

  • sqrt(double a):返回非负 double 的正平方根(正确舍入)。
  • cbrt(double a):返回 double 的立方根(可正可负)。

2、随机数生成:random

Math.random() 返回一个++大于等于++ 0.0 ++且小于++ 1.0 的**++随机++** **++double++**值,每次调用返回不同结果:

java 复制代码
// 生成 1-100 之间的随机整数
int randomInt = (int) (Math.random() * 100) + 1;
System.out.println("随机整数(1-100):" + randomInt);

注意Math.random() 是线程安全的,但在多线程环境下性能较差。若需高性能随机数,可考虑 java.util.Random 或***ThreadLocalRandom***。

3、符号与 ulp 操作

  • signum:返回参数的符号(正为 1.0,负为 -1.0,零为 0.0)。
  • ulp:返回参数的 ulp(单位在最后一位)大小,用于衡量浮点精度。
java 复制代码
// signum 示例
System.out.println(Math.signum(5.2)); // 输出:1.0
System.out.println(Math.signum(-3.8)); // 输出:-1.0
System.out.println(Math.signum(0.0)); // 输出:0.0

// ulp 示例
System.out.println(Math.ulp(1.0)); // 输出:2.220446049250313e-16(1.0 的 ulp)
System.out.println(Math.ulp(1000000.0)); // 输出:0.0001220703125(大数的 ulp 更大,精度更低)

ulp 全称 Unit in the Last Place(最后一位的单位),是衡量浮点数精度的核心指标。
浮点数(如 floatdouble)在计算机中是离散表示 的(而非连续的实数),因为它们的存储位数有限(例如 IEEE 754 单精度浮点数用 23 位表示尾数,双精度用 52 位)。这意味着:两个相邻的、可被精确表示的浮点数之间存在一个最小差值 ,这个差值就是该浮点数的 ulp

举个例子:

  • 对于单精度浮点数(float):
    当数值较小时(如 1.0f),相邻可表示的浮点数非常接近,ulp(1.0f) 约为 1.19e-7(即 2−23,因为单精度尾数是 23 位);
    当数值很大时(如 223 附近),ulp 会变大(此时 ulp(2^23)1.0f),因为尾数的有限位数无法再表示更小的间隔 ------ 这就是浮点数 "精度随数值增大而下降" 的原因。
    ulp 是浮点数精度的 "尺子",主要用于数值计算的误差分析合理比较浮点数,具体场景包括:
1. 衡量浮点数的 "接近程度"(替代直接相等判断)

浮点数计算中,由于舍入误差(如 0.1 + 0.2 不等于 0.3),直接用 == 比较是否相等往往不准确。此时可以用 ulp 判断两个数是否 "足够接近":

如果两个数的差值小于 k 倍的 ulp(k 通常取 1 或 2),则认为它们在数值上是等效的。

java 复制代码
// 判断 a 和 b 是否接近(差值 < 2 倍 ulp)
boolean isClose(double a, double b) {
    return Math.abs(a - b) < 2 * Math.ulp(Math.min(a, b));
}
2. 分析数值算法的精度

在科学计算(如物理模拟、工程计算)中,需要评估算法的误差是否在可接受范围内。ulp 可以量化误差大小:

  • 若计算结果与理论值的差值在 1-2 个 ulp 内,说明算法精度极高(接近浮点数的理论极限);
  • 若误差达到 100 个 ulp 以上,可能需要优化算法(如减少舍入累积)。
3. 调试浮点计算异常

当数值计算出现 "奇怪的偏差" 时,ulp 可以帮助定位问题:

例如,若一个本应精确的计算(如 2.0 / 2.0)结果与理论值的差值超过 1 个 ulp,可能是代码中存在类型转换错误(如 floatdouble 混用)或溢出。

signum 函数的作用是提取数值的 "符号信息"(正 / 负 / 零),实际用途集中在 "需要根据方向做决策" 的场景

四、资料来源

Math类

还有一些我会继续加入进来的......

相关推荐
梦想的初衷~8 分钟前
MATLAB近红外光谱分析技术及实践技术应用
开发语言·支持向量机·matlab
探索java9 分钟前
深入解析 Spring 获取 XML 验证模式的过程
xml·java·spring
找不到、了14 分钟前
Java设计模式之<装饰器模式>
java·设计模式·装饰器模式
Fly-ping20 分钟前
【前端】JavaScript文件压缩指南
开发语言·前端·javascript
java叶新东老师25 分钟前
解决windows系统下 idea、CLion 控制台中文乱码问题
java·windows·intellij-idea
铭哥的编程日记28 分钟前
《C++ list 完全指南:从基础到高效使用》
开发语言·c++·list
岁忧1 小时前
(LeetCode 面试经典 150 题 ) 155. 最小栈 (栈)
java·c++·算法·leetcode·面试·go
lsx2024061 小时前
Go 错误处理
开发语言
山风呼呼1 小时前
golang--通道和锁
开发语言·后端·golang
yourkin6661 小时前
为什么现在 Spring Boot 默认使用 CGLIB 了?
java·开发语言·jvm