Java双比较ε

Java双比较ε,java,floating-point,currency,Java,Floating Point,Currency,我编写了一个类,用Java中的两个double测试等式、小于和大于。我的一般情况是比较价格,精确到半美分。59.005与59.395相比。我选择的ε是否适合这些情况 private final static double EPSILON = 0.00001; /** * Returns true if two doubles are considered equal. Tests if the absolute * difference between two doubles has

我编写了一个类,用Java中的两个double测试等式、小于和大于。我的一般情况是比较价格,精确到半美分。59.005与59.395相比。我选择的ε是否适合这些情况

private final static double EPSILON = 0.00001;


/**
 * Returns true if two doubles are considered equal.  Tests if the absolute
 * difference between two doubles has a difference less then .00001.   This
 * should be fine when comparing prices, because prices have a precision of
 * .001.
 *
 * @param a double to compare.
 * @param b double to compare.
 * @return true true if two doubles are considered equal.
 */
public static boolean equals(double a, double b){
    return a == b ? true : Math.abs(a - b) < EPSILON;
}


/**
 * Returns true if two doubles are considered equal. Tests if the absolute
 * difference between the two doubles has a difference less then a given
 * double (epsilon). Determining the given epsilon is highly dependant on the
 * precision of the doubles that are being compared.
 *
 * @param a double to compare.
 * @param b double to compare
 * @param epsilon double which is compared to the absolute difference of two
 * doubles to determine if they are equal.
 * @return true if a is considered equal to b.
 */
public static boolean equals(double a, double b, double epsilon){
    return a == b ? true : Math.abs(a - b) < epsilon;
}


/**
 * Returns true if the first double is considered greater than the second
 * double.  Test if the difference of first minus second is greater then
 * .00001.  This should be fine when comparing prices, because prices have a
 * precision of .001.
 *
 * @param a first double
 * @param b second double
 * @return true if the first double is considered greater than the second
 *              double
 */
public static boolean greaterThan(double a, double b){
    return greaterThan(a, b, EPSILON);
}


/**
 * Returns true if the first double is considered greater than the second
 * double.  Test if the difference of first minus second is greater then
 * a given double (epsilon).  Determining the given epsilon is highly
 * dependant on the precision of the doubles that are being compared.
 *
 * @param a first double
 * @param b second double
 * @return true if the first double is considered greater than the second
 *              double
 */
public static boolean greaterThan(double a, double b, double epsilon){
    return a - b > epsilon;
}


/**
 * Returns true if the first double is considered less than the second
 * double.  Test if the difference of second minus first is greater then
 * .00001.  This should be fine when comparing prices, because prices have a
 * precision of .001.
 *
 * @param a first double
 * @param b second double
 * @return true if the first double is considered less than the second
 *              double
 */
public static boolean lessThan(double a, double b){
    return lessThan(a, b, EPSILON);
}


/**
 * Returns true if the first double is considered less than the second
 * double.  Test if the difference of second minus first is greater then
 * a given double (epsilon).  Determining the given epsilon is highly
 * dependant on the precision of the doubles that are being compared.
 *
 * @param a first double
 * @param b second double
 * @return true if the first double is considered less than the second
 *              double
 */
public static boolean lessThan(double a, double b, double epsilon){
    return b - a > epsilon;
}
private final static double EPSILON=0.00001;
/**
*如果两个双精度被视为相等,则返回true。测试是否为绝对值
*两个双打之间的差值小于.00001。这
*在比较价格时应该是可以的,因为价格具有
* .001.
*
*@param是一个双重比较。
*@param b双精度可供比较。
*@return true如果两个double被认为相等,则返回true。
*/
公共静态布尔等于(双a,双b){
返回a==b?true:Math.abs(a-b)ε;
}
/**
*如果认为第一个双精度值小于第二个双精度值,则返回true
*加倍。测试第二次减去第一次的差值是否大于
* .00001.  在比较价格时,这应该是很好的,因为价格有
*精度为0.001。
*
*@param a第一双
*@param b第二双
*@如果第一个双精度被认为小于第二个双精度,则返回true
*双重的
*/
公共静态布尔lessThan(双a,双b){
返回值小于(a,b,ε);
}
/**
*如果认为第一个双精度值小于第二个双精度值,则返回true
*加倍。测试第二次减去第一次的差值是否大于
*给定的双(ε)。确定给定的ε非常重要
*取决于正在比较的双精度。
*
*@param a第一双
*@param b第二双
*@如果第一个双精度被认为小于第二个双精度,则返回true
*双重的
*/
公共静态布尔lessThan(双a、双b、双ε){
返回b-a>epsilon;
}

是。Java Double将比给定的epsilon 0.00001更精确

由于存储浮点值而发生的任何舍入误差将小于0.00001。我经常使用
1E-6
或0.000001表示Java中的双ε,没有任何问题


另一方面,我喜欢
epsilon=1E-5的格式因为我觉得它更可读(Java中的1E-5=1 x 10^-5)。1E-6在读取代码时很容易与1E-5区分,而0.00001和0.000001在查看代码时看起来非常相似,我认为它们是相同的值。

哇哇哇哇哇哇哇哇哇哇。您使用浮点数作为货币是否有特定的原因,或者使用浮点数是否会更好?我不知道您要解决的具体问题是什么,但您应该考虑半美分是否真的是您想要处理的东西,或者它是否只是使用不精确数字格式的产物。

您不使用double表示金钱。从来没有。改用

然后,您可以指定如何精确地进行舍入(在金融应用程序中,这有时是由法律规定的!),而不必进行像epsilon这样的愚蠢操作


说真的,使用浮点类型来表示货币是非常不专业的。

浮点数字只有这么多有效数字,但它们可以更高。如果你的应用程序曾经处理过大量数据,你会注意到epsilon值应该是不同的

0.001+0.001=0.002 但是 12,345,678,900,000,000,000,000+1=12,345,678,900,000,000,000,000
如果您使用的是浮点和双精度。这不是一个很好的金钱表现,除非你他妈的确定你在这个系统中永远不会处理超过一百万美元的事情

美分?如果你在计算货币价值,你真的不应该使用浮动价值。金钱实际上是可数的价值。美分或便士等可以被视为整数的两个(或任何)最低有效位。您可以将货币值存储为整数并除以100(例如,在最后两位数字之前放置点或逗号2)。使用浮点会导致奇怪的舍入错误


无论如何,如果你的ε应该定义精度,那么它看起来有点太小(太精确)…

如果你是在处理钱的问题,我建议检查钱的设计模式(最初来自)

我建议阅读此链接了解动机:

boolean equal(double d1, double d2) { double d = d1 / d2; return (Math.abs(d - 1.0) < 0.001); }

/**
  *@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);
}
    double a = 10.0;
    double b = 10.0 + EPSILON;
    if (!equals(a, b)) {
        System.out.println("OK: " + a + " != " + b);
    } else {
        System.out.println("ERROR: " + a + " == " + b);
    }
    ERROR: 10.0 == 10.00001