当前位置:  开发笔记 > 编程语言 > 正文

Java双重比较epsilon

如何解决《Java双重比较epsilon》经验,为你挑选了5个好方法。

我写了一个类来测试相等,小于和大于Java中的两个双重.我的一般情况是比较可以具有半分精度的价格.59.005比59.395.我选择的epsilon适合这些情况吗?

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;
}

Michael Borg.. 104

你不要用double来代表金钱.永远不会.请java.math.BigDecimal改用.

然后你可以指定如何精确地进行舍入(有时在金融应用程序中由法律规定!)并且不必像这个epsilon那样做愚蠢的黑客攻击.

说真的,使用浮点类型来代表金钱是非常不专业的.



1> Michael Borg..:

你不要用double来代表金钱.永远不会.请java.math.BigDecimal改用.

然后你可以指定如何精确地进行舍入(有时在金融应用程序中由法律规定!)并且不必像这个epsilon那样做愚蠢的黑客攻击.

说真的,使用浮点类型来代表金钱是非常不专业的.


+1因为你确实没有使用浮点数代表金钱而是-1(所以我没有修改你的数量),因为使用epsilon几乎不是"愚蠢的黑客".它是科学计算的基础,而不是"愚蠢的黑客".戈德伯格关于这一主题的论文同意这一点.
说真的,你不应该只是因为这就是你做事的方式,这是所有情况下最好的方法.在四家不同的银行工作过,我从来没有见过使用BigDecimal的交易系统,也没有推荐使用它们.
彼得,你会推荐什么钱呢?我的偏好是很长的.基于短期的Money类组合.然而,我非常犹豫为自己的情况而努力.我之前已经完成了......但它不是我可以证明有效的东西.
您很可能需要使用一些“十进制”类来处理实际的资金转移,尤其是对于零售客户。那是“会计软件”,但并非所有“财务软件”都是“会计”。一个交易系统处理A)预计现金流量及其现值,这是模型计算的结果,使用BigDecimal来存储这些数字是没有意义的,B)实际现金流量足够大,人们不必担心便士损失。说真的
@RichardGomes暗示有一个正确的答案没有被现实反映出来。无论选择哪个,都会出现表示错误。固定精度的问题是,由于编码错误,我宁愿比0.000000001多出10倍或更多。

2> Alex B..:

是.Java双精度将比你给出的0.00001的epsil更好.

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

在相关的说明中,我喜欢格式,epsilon = 1E-5;因为我觉得它更具可读性(Java中的1E-5 = 1 x 10 ^ -5).读取代码时,1E-6很容易与1E-5区分,而当看到代码时,0.00001和0.000001看起来非常相似,我认为它们是相同的值.



3> Josh Lee..:

哇哇哇哇 您是否有特定的原因使用浮点货币,或者使用任意精度的定点数字格式会更好?我不知道你要解决的具体问题是什么,但你应该考虑半分钱是否真的是你想要使用的东西,或者它只是一个使用不精确数字格式的工件.



4> carlosvin..:

如果你可以使用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);
}



5> Yuval Adam..:

如果你正在处理钱,我建议检查Money设计模式(最初来自Martin Fowler关于企业架构设计的书).

我建议阅读此链接以获取动机:http: //wiki.moredesignpatterns.com/space/Value+Object+Motivation+v2


moredesignpatterns服务器似乎已经消失并且没有被替换.该文章在archive.org上,但是:http://web.archive.org/web/20090105214308/http://wiki.moredesignpatterns.com/space/Value%2BObject%2BMotivation%2Bv2
推荐阅读
惬听风吟jyy_802
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有