[英]Java BigDecimal Round Down issue
我有一些简单的代码可以向上和向下取整,但它产生了一些意想不到的结果。
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
double a = 46.66;
System.out.println("Roundup: " + roundUp(a,2) + "\nRound Down: " + roundDown(a,2));
}
public static double roundUp(double a, int scale)
{
BigDecimal value = new BigDecimal(a);
value = value.setScale(scale, RoundingMode.UP);
return value.doubleValue();
}
public static double roundDown(double a, int scale)
{
BigDecimal value = new BigDecimal(a);
value = value.setScale(scale, RoundingMode.DOWN);
return value.doubleValue();
}
当我在小数点后使用 3 位数字时,它按预期工作。 如果 a = 44.661,则输出如下所示。
上整:46.67 下整:46.66
当 a=44.66 时,向下舍入的值减少 1,这是出乎意料的,如下所示。
上整:46.66 下整:46.65
如何在仍然保留上述结果的同时获得 44.66 的舍入和 44.67 的舍入。
在此先感谢您的帮助
那是因为您并没有真正使用 BigDecimals,而是使用了双精度数。 当您键入44.66
它会转换为双精度值,从而导致值略小于 44.66。 BigDecimal
无法修复在您提供输入之前已经发生的舍入错误。
试试这个。
public static void main(String[] args) throws Exception {
BigDecimal a = new BigDecimal("46.66");
System.out.println("Roundup: " + roundUp(a,2) + "\nRound Down: " + roundDown(a,2));
}
public static BigDecimal roundUp(BigDecimal a, int scale)
{
return a.setScale(scale, RoundingMode.UP);
}
public static BigDecimal roundDown(BigDecimal a, int scale)
{
return a.setScale(scale, RoundingMode.DOWN);
}
你可以做的是使用 BigDecimal.valueOf 向上或向下舍入
BigDecimal value = BigDecimal.valueOf(a);
这补偿了双打的表示误差,但是如果您也有一些算术舍入误差,这可能还不够。
相反,您需要确定您可以拥有的最大舍入误差是多少
public static double roundUp2(double d) {
return Math.ceil(d * 100 - ERR)/100.0;
}
public static double roundHalf2(double d) {
return Math.ceil(d * 100)/100.0;
}
public static double roundDown2(double d) {
return Math.floor(d * 100 + ERR)/100.0;
}
我相信您真正需要的是执行以下功能:
private static void roundUp(double num, int decimalPlaces){
for (int i =0; i< decimalPlaces; ++i){
num*=10;
}
int tmp = (int) (num+0.5);
num = tmp;
for (int i =0; i< decimalPlaces; ++i){
num = num/10;
}
}
您可以使用替代方法进行四舍五入,只需将“num+0.5”更改为“num - 0.5”。 但是,由于机器浮点数错误,这可能会在打印时造成麻烦。 但是你也可以为此做点什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.