Math.ulp() 返回指定浮点数在 IEEE 754 下相邻可表示数的间距,即“单位末位”(ULP),其值随数值增大而增大、符号无关、0.0 返回最小正次正规数的 ULP,NaN 或无穷大返回 NaN。
Math.ulp() 返回的是指定浮点数值在 IEEE 754 格式下**相邻可表示数之间的间距**,也就是该值所在数量级的最小可分辨差值——常称“单位末位”(Unit in the Last Place, ULP)。它不是固定常量,而是随数值大小动态变化的精度标尺。
ULP 随数值大小变化的规律数值越大,ULP 越大,意味着精度下降;数值越小(尤其接近零),ULP 越小,但有下限:Math.ulp(1.0) ≈ 2.22e−16(即 2⁻⁵²),这是 double 类型在 1 附近的典型精度Math.ulp(2.0) = 4.44e−16(翻倍,因指数位 +1)
Math.ulp(100.0) ≈ 2.84e−14,比 1.0 大约 100 倍Math.ulp(0.0) 返回 Double.MIN_NORMAL 的 ULP(约 4.9e−324),而非 0 —— 这是标准对次正规数区域的约定Math.ulp(-5.0) == Math.ulp(5.0),符号不影响结果正确调用 ulp() 的关键点避免常见误用,需注意类型、语义和边界:传入具体数值,不是类型或表达式:用 Math.ulp(x),而不是 Math.ulp(double.class)区分 float 和 double 版本:Math.ulp(1.0f) ≈ 1.19e−7,远粗于 double 版本,混用易引入隐式转换误差对 NaN 或 Infinity,返回 NaN 或 Infinity;对 ±0.0,统一返回最小正次正规数的 ULP不建议对未经校验的中间计算结果直接取 ulp —— 若该值本身已因溢出/下溢失真,其 ulp 就失去参考意义ULP 在误差判定中的实用方式相比固定容差(如 1e−9),以 ULP 为单位设定比较阈值,能适配不同数量级的数值:计算绝对误差:double diff = Math.abs(a - b)选取合理参考值取 ulp:常用 Math.max(Math.abs(a), Math.abs(b)),确保容差围绕更“权威”的量级判断是否在 N 个 ULP 内:diff <= N * Math.ulp(ref),N 通常取 1~4,高精度场景可收紧,工程验证常取 2~3零值需单独处理:if (a == 0.0 && b == 0.0) return true;或用 Double.compare(a, b) == 0 辅助判等ULP 与 nextUp 的关系Math.nextUp(x) 返回比 x 大一个 ULP 的下一个可表示 double 值,即 nextUp(x) == x + Math.ulp(x)(在未溢出前提下成立):Math.nextUp(0.0) ≈ 4.9e−324,正好等于 Math.ulp(0.0) Math.nextUp(1.0) = 1.0000000000000002,差值即为 Math.ulp(1.0)该关系在非次正规、非边界区域严格成立,是验证 ulp 计算是否合理的直观方式
