我正在用 Java 开发时间关键算法,因此我没有使用 BigDecimal
。为了处理舍入误差,我设置了一个误差上限,低于该上限的不同 float 被认为是完全相同的。现在的问题是那个界限应该是什么?或者换句话说,在使用 float 执行计算运算(浮点加法、减法、乘法和除法)时,可能发生的最大舍入误差是多少?
根据我做过的实验,1e-11
的范围似乎就足够了。
PS:这个问题与语言无关。
编辑:我正在使用 double
数据类型。这些数字是使用 Random
的 nextDouble()
方法生成的。
编辑 2:看来我需要根据我使用的 float 的生成方式来计算误差。 nextDouble()
方法如下所示:
public double nextDouble() {
return (((long)(next(26)) << 27) + next(27))
/ (double)(1L << 53); }
根据这个方法中的常量,我应该能够计算出用这个方法生成的 float 可能出现的最大误差(它的机器 epsilon?)。如果有人可以发布计算结果,我们会很高兴。
最佳答案
单个简单运算的最坏情况舍入误差是包含运算实数结果的一对 double 之间差距的一半。 Random 的 nextDouble 方法的结果是“from the range 0.0d (inclusive) to 1.0d (exclusive)”。对于这些数字,最大差距约为 1e-16,最坏情况下的舍入误差约为 5e-17。
这是一个打印一些样本数的差距的程序,包括 Random 的 nextDouble 的最大结果:
public class Test {
public static void main(String[] args) {
System.out.println("Max random result gap: "
+ Math.ulp(Math.nextAfter(1.0, Double.NEGATIVE_INFINITY)));
System.out.println("1e6 gap: "
+ Math.ulp(1e6));
System.out.println("1e30 gap: "
+ Math.ulp(1e30));
}
}
输出:
Max random result gap: 1.1102230246251565E-16
1e6 gap: 1.1641532182693481E-10
1e30 gap: 1.40737488355328E14
根据您正在进行的计算,错误可能会在多个操作中累积,从而产生比您从这种简单的单一操作方法中预测的更大的总舍入误差。正如 Mark Dickinson 在评论中所说,“数值分析比这要复杂一点。”
关于java - 计算 float 时可能出现的最大舍入误差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30882963/