我有一些带有算术表达式的业务逻辑,其结果如下
(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位小数而不是每次舍入?
答案 0 :(得分: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;
答案 1 :(得分:1)
基本问题是
System.out.println(10.0 * 20.58);
打印
205.79999999999998
由于20.58
中的表示错误,有一个小的舍入误差
您需要
int
或long
。在最后一种情况下,相同的操作将会读取
System.out.println(10 * 2058);
打印
20580
这是你需要的值的100倍作为其固定精度,例如美分而非美元。
答案 2 :(得分:1)
对于基数10,有些分数无法用有限的位数精确表达,例如1/3 = 0.33333333 ....
与基数2相同,除了产生这种结果的分频器不是我们习惯的分频器,例如,对于20.58,即2058/100,情况就是如此。
在内部,双精度数和浮点数用位(非数字)存储,因此double或float的确切值不能存储在计算机的内存中。每次使用此值执行操作时,由于近似值,您会得到一个小的移位,当转换回十进制格式进行打印时,该移动变得可见。
在进行精度很重要的计算时,你必须注意这一点。
所以你有两个解决方案:
答案 3 :(得分:0)
使用float
代替double
System.out.println((float)((10.0f * 20.58f)/1.0f));
输出
205.8
答案 4 :(得分: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