繁体   English   中英

如何以 epsilon 精度检查 a ≤ b

[英]How to check if a ≤ b with an epsilon precision

所以我有两个双打, ab ,我需要检查a ≤ b是否具有给定 epsilon 的精度。

因此,要检查a == b我是否需要这样做( ab是双精度数, EPSILON是最终双精度数,在我的情况下为 0.001):

Math.abs(a - b) < EPSILON

作为我自己问题的答案,我的想法是:

a < EPSILON + b

我的问题是,以 epsilon 为精度,在最终结果中小于和小于或等于之间有什么区别,也许有人有更好的方法来编写它?

你不想写a < EPSILON+b ,因为如果b很大,那么你可能有b == EPSILON+b ,然后如果ab完全相等, a < EPSILON+b就会失败。

(ab) < EPSILON有效。

在比较具有“epsilon 精度”的数字时,如果它们在 EPSILON 内,您认为数字是相同的,因此“a < b,具有 epsilon 精度”实际上是:

(ab) <= -EPSILON

如果您可以使用 BigDecimal,则使用它,否则:

/**
  *@param precision number of decimal digits
  */
public static boolean areEqualDouble(double a, double b, int precision) {
   return Math.abs(a - b) <= Math.pow(10, -precision);
}

更新:这篇文章是错误的,请参阅评论。 @matttimmens 的回答似乎是合法的。 (我仍然需要检查极端情况)

更新 2我检查并学习了。 我想我会找到像整数这样的极端情况。 在 Java 中, (Integer.MIN_VALUE == ((-Integer.MIN_VALUE)))为真。 这是因为 integer 数字(如:非小数、非浮点数)具有不对称范围:

  • 第一个正数是0,第一个负数是-1,因此
  • 字节:MAX_VALUE 是 127,而 MIN_VALUE 是 -128,所以MAX_VALUE != -MIN_VALUEMIN_VALUE != MAX_VALUE
  • 也适用于short,int,long

这与静默 integer 溢出混合在一起,在极端角落工作时会产生问题,尤其是一对一问题:

    final int a = Integer.MIN_VALUE;
    final int b = Integer.MAX_VALUE;
    final int eps = 1;
    System.out.println("a-b = " + (a - b));
    System.out.println((a - b) < eps);

ab结果为1 ,并且1 < eps为假,尽管我们清楚地看到 a 比 b 小很多。 这是算法在整数上失败的一种极端情况。 注意: OP 是关于doubles的。

然而,Java(float,double)中的浮点数,或者更确切地说,对它们的操作,补偿,并且不允许发生溢出:

  • (Double.MAX_VALUE + 1) == Double.MAX_VALUE成立
  • (Double.MAX_VALUE + Double.MAX_VALUE) == Double.POSITIVE_INFINITY成立
  • (-Double.MAX_VALUE + -Double.MAX_VALUE) == Double.NEGATIVE_INFINITY成立

因此,在使用整数之前,+1 或 -1 无声 integer 溢出会导致问题。 因此,当向一个非常大的 double 变量添加 +1(或 -1 或任何小数)时,更改会丢失到四舍五入。 因此,极端情况在这里不起作用,@matttimmens 的解决方案(ab)<e与浮点变量一样接近事实,舍入到一边。

我以前的错误帖子:

要反驳@matttimmens 的回复,请运行该代码:

    final double a = Double.MIN_VALUE;
    final double b = Double.MIN_VALUE + 0;
    final double c = Double.MIN_VALUE + 10;
    final double e = 0.001;
    System.out.println("Matches 1: " + ((a - b) < e));
    System.out.println("Matches 2: " + ((b - a) < e));
    System.out.println("Matches 3: " + ((a - c) < e));
    System.out.println("Matches 4: " + ((c - a) < e));

第 3 场比赛给出了错误的结果,因此他的答案是错误的。

有趣的是,他想到了改变大的数字,却让非常小的数字无人看管。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM