首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何判断两个双打是否几乎相等?

如何判断两个双打是否几乎相等?
EN

Stack Overflow用户
提问于 2017-04-07 22:39:57
回答 3查看 9.6K关注 0票数 3

我正在试图找到一些Java代码来确定两个双倍是否几乎相等。我做了很多谷歌搜索,并找到了零碎,我已经放在这里。它开始逃离我的地方是使用“相对感受器”。这个方法看起来就像我要找的。我不想直接指定epsilon,但是我想根据这两个参数的大小使用epsilon。这是我整理的代码,我需要检查一下。(P.S.我知道的数学刚刚够危险的。)

代码语言:javascript
复制
public class MathUtils
{
    // http://stackoverflow.com/questions/3728246/what-should-be-the-
    // epsilon-value-when-performing-double-value-equal-comparison
    // ULP = Unit in Last Place
    public static double relativeEpsilon( double a, double b )
    {
        return Math.max( Math.ulp( a ), Math.ulp( b ) );
    }

    public static boolean nearlyEqual( double a, double b )
    {
        return nearlyEqual( a, b, relativeEpsilon( a, b ) );
    }

    // http://floating-point-gui.de/errors/comparison/
    public static boolean nearlyEqual( double a, double b, double epsilon )
    {
        final double absA = Math.abs( a );
        final double absB = Math.abs( b );
        final double diff = Math.abs( a - b );

        if( a == b )
        {
            // shortcut, handles infinities
            return true;
        }
        else if( a == 0 || b == 0 || absA + absB < Double.MIN_NORMAL )
        {
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            // NOT SURE HOW RELATIVE EPSILON WORKS IN THIS CASE
            return diff < ( epsilon * Double.MIN_NORMAL );
        }
        else
        {
            // use relative error
            return diff / Math.min( ( absA + absB ), Double.MAX_VALUE ) < epsilon;
        }
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-04-07 22:48:46

我会为此使用一个库,我通常使用的是谷歌番石榴图书馆的DoubleMath库。https://google.github.io/guava/releases/19.0/api/docs/com/google/common/math/DoubleMath.html

if (DoubleMath.fuzzyEquals(a, b, epsilon)) { // a and b are equal within the tolerance given }还有一个fuzzyCompare。

票数 10
EN

Stack Overflow用户

发布于 2017-04-08 05:25:52

比较两个浮动值a,b的常用方法是:

代码语言:javascript
复制
if ( Math.abs(a-b) <= epsilon ) do_stuff_if_equal;
 else                       do_stuff_if_different;

其中Math.abs()是绝对值。由于我不使用JAVA编写代码,如果情况并非如此,则需要使用double变体。epsilon是你的不同之处。正如前面提到的,ulp太小了,无法做到这一点。您需要使用对您正在比较的值有意义的值。那么如何计算epsilon呢?

这有点棘手,是的,可以使用a,b的大小,但这不是一种健壮的方法,因为如果a,b的指数太不同,您可以很容易地获得假阳性。相反,你应该使用一个意义-完整的价值。例如,如果您正在比较位置坐标,那么epsilon应该是最小细节的分数,或者是您认为是相同点的最小距离。对于角度,一些很小的角度,比如1e-6 deg,但是这个值取决于你所使用的范围和精度。对于规范化的<-1,1>范围,我通常使用1e-101e-30

正如你所看到的,epsilon主要取决于目标的精确性和大小,并且在不同的情况下都有很大的变化,所以创建一些统一的方法(像您想要的那样摆脱epsilon )是不安全的,只会导致以后的头部疼痛。

为了简化这一点,我通常定义一个可以更改的_zero常量或变量(在计算类的情况下)。将其设置为默认值,这对大多数情况都足够好,如果在某一时刻引起问题,我知道我可以很容易地更改它……

如果您想按自己的方式做(忽略上面的文本),那么您可以这样做:

代码语言:javascript
复制
if (Math.abs(a)>=Math.abs(b)) epsilon=1e-30*Math.abs(b);
 else                         epsilon=1e-30*Math.abs(a);

但正如我所说,这可能导致错误的结果。如果您坚持使用ulp,那么我将使用Min而不是Max

票数 0
EN

Stack Overflow用户

发布于 2020-08-18 05:43:38

您可以使用来自Apache Commons Math的类Apache Commons Math。示例:

代码语言:javascript
复制
if (Precision.equals(sum, price, 0.009)) {
    // arguments are equal or within the range of allowed error (inclusive)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43288079

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档