1

我有一些带有算术表达式的业务逻辑,它们的结果如下

(10.0 * 20.58)/1.0=205.7999..98
(6.0 * 37.9)/1.0=227.3999..98
(5.0 * 50.0)/1.0=250.0
(10.0 * 37.9)/1.0=379.0

但预期的结果是

(10.0 * 20.58)/1.0=205.8
(6.0 * 37.9)/1.0=227.4
(5.0 * 50.0)/1.0=250.0
(10.0 * 37.9)/1.0=379.0

我不清楚为什么我们会得到 .999..98 小数部分?因此,我的等式比较失败了,因此业务逻辑也失败了。对于我们正在使用的少数情况

amt = (double)Math.round(orderAmt*100000)/100000;

但这不可能在我们有双重算术表达式的每个地方都做同样的事情。

我想知道为什么我们随机得到这样的结果,是否有可能将结果四舍五入到小数点后 5 位而不是四舍五入?

4

5 回答 5

1

你可以使用BigDecimal四舍五入

BigDecimal bd = new BigDecimal((10.0 * 20.58)/1.0) ;
bd = bd.setScale(4, RoundingMode.UP);

与静态方法一起使用

public static double round(double value, int digits) {
    BigDecimal bd = new BigDecimal(value);
    return bd.setScale(digits, RoundingMode.UP).doubleValue();
}

RoundingMode拥有 :

RoundingMode.UP;
RoundingMode.DOWN;
RoundingMode.HALF_DOWN;
RoundingMode.HALF_EVEN;
于 2012-11-15T14:15:31.220 回答
1

基本问题是

System.out.println(10.0 * 20.58);

印刷

205.79999999999998

由于表示错误,有一个小的舍入误差20.58

你要么需要

  • 在比较之前对结果进行四舍五入。
  • 使用允许一些错误的比较
  • 使用 BigDecimal(在大多数情况下过度杀戮)
  • 使用美分而不是美元,即使用intlong以固定精度。

在最后一种情况下,相同的操作将读取

System.out.println(10 * 2058);

印刷

20580

这是您需要的固定精度值的 100 倍,例如美分而不是美元。

于 2012-11-15T14:46:19.013 回答
1

对于基数 10,有些分数不能用有限的数字精确表示,例如 1/3 = 0.33333333....

基数 2 也是一样,只是产生这种结果的除法器不是我们习惯的那种,比如 20.58 就是 2058 / 100 就是这样。

在内部,双精度和浮点数与位(非数字)一起存储,因此双精度或浮点数的确切值无法存储在计算机的内存中。每次使用此值执行操作时,您都会得到一个小的偏移,因为近似值在转换回十进制格式进行打印时变得可见。

在执行精度很重要的计算时,您必须注意这一点。

所以你有两个解决方案:

  • 以十进制类型存储所有数字并使用它执行所有计算。这将实现准确性,但以性能为代价。
  • 您还可以使用 double 或 float 保留所有计算,并使用固定位数格式化仅用于打印结果。
于 2012-11-15T14:50:14.863 回答
0

使用float代替double

http://ideone.com/L9vwR8

System.out.println((float)((10.0f * 20.58f)/1.0f));

输出

205.8

于 2012-11-15T14:21:18.730 回答
0

您可能希望使用double如下舍入:

    double roundingPlaces = 10.0;//use 10.0 for single decimal digit rounding
    double a1 = 10.0;
    double b1 = 20.58;
    double c1 = 1.0;
    System.out.println(Math.round((a1*b1*roundingPlaces)/c1)/roundingPlaces);

这将打印 205.8。

    float fa1 = (float) 10.0;
    float fb1 = (float)20.58;
    float fc1 = (float)1.0;
    System.out.println(fa1*fb1/fc1);    

这也打印 205.8

于 2012-11-15T14:25:46.343 回答