验证双值范围和步骤

时间:2009-12-22 08:57:44

标签: floating-point range algorithm precision floating-accuracy

我正在尝试构建一个算法,该算法验证double值是使用min,max和step值定义的范围的成员。问题是检查该值是否符合步骤规则。对于整数,这很容易做到:

 boolean validate(int value, int min, int step, int max){
      return value >= min &&
             value <= max &&

             //Step should be relative to the min value not to 0.
             (value-min) % step == 0;  
 }

然而,这对双值不起作用。我知道这至少部分是出于精确原因,我尝试通过将所有值乘以一个非常高的数字并将它们转换为long来破解解决方案。这对于所有值都不起作用,并且在检查余数时也没有允许小偏差为0。有谁有这个问题,并提出了一个很好的解决方案?以下是一个以非工作验证方法为特色的示例和测试。

这样做的一种方法是从最小值开始并逐步递增,直到它等于或大于输入值,但除了一个丑陋的解决方案,这可能是我的应用程序中的潜在瓶颈,所以我真的想避免它。

我很感激任何指示......

问候/亨里克

public class ValidationExample {

public static void main(String[] args) {
    /*Range: 
        min  -10.5
        step .3
        max  -5
    */

    //Invalid values
    double[] a = {-11,-10.6,-10.4,-10.3,-10.1,-10.0,-9.8,-9.7,
            -9.5,-9.4,-9.2,-9.1,-8.9,-8.8,-8.6,-8.5,-8.3,
            -8.2,-8,-7.9,-7.7,-7.6,-7.4,-7.3,-7.1,-7.0,
            -6.8,-6.7,-6.5,-6.4,-6.2,-6.1,-5.9,-5.8,-5.6,
            -5.5,-5.3,-5.2,-5.0,-4.9,-4.8,2};

    //Valid values
    double[] b = {-10.5,-10.2,-9.9,-9.6,-9.3,-9.0,-8.7,-8.4,
            -8.1,-7.8,-7.5,-7.2,-6.9,-6.6,-6.3,-6.0,-5.7,
            -5.4,-5.1};

    for(double d : a){
        if(validate(d,-10.5,.3,-5))
            System.err.println(d + " was considered valid.");
    }

    for(double d : b){
        if(!validate(d, -10.5,.3,-5))
            System.err.println(d + " was considered invalid");
    }

    /*
     * Range
     *  min  2
     *  step .05
     *  max  3
     */

    //Invalid values
    double[] c = {1.09,2.055,2.06,2.14,2.16,2.56,2.97,3.05};

    //Valid values
    double[] e = {2.0,2.05,2.1,2.15,2.2,2.25,2.5,2.75,2.95,3.0};

    for(double d : c){
        if(validate(d,2,.05,3))
            System.err.println(d + " was considered valid.");
    }

    for(double d : e){
        if(!validate(d,2,.05,3))
            System.err.println(d + " was considered invalid.");
    }

}

private static boolean 
    validate(double value, double min, double step, double max){
    return value >= min && 
           value <= max &&
           (value - min) % step == 0;
}

}

2 个答案:

答案 0 :(得分:3)

如果value遵循步骤规则,则(value - min)/step应为整数。因此,您可以检查它与最近的整数的接近程度,并确定距离是否重要。

double ratio = (value-min)/step;
double distance = Math.Abs(ratio - Math.Round(ratio,0));
return distance < treshold;

答案 1 :(得分:1)

除了不那么优雅,并且可能很慢之外,连续添加step以接近正在检查的数字将导致计算不准确,因为浮点错误往往会累积。

我不太了解Java,但执行此操作的算法是采用比率:(value-min)/step,将其四舍五入到最接近的整数n,然后计算v = min+step*n 。如果vvalue“足够接近”,则可以将value标记为有效。

要测试“足够接近”的浮点值,应使用相对和绝对容差。例如,包fcmp实现了一个相当好的算法来比较浮点值。