Java 如何使用BigDecimal.round\u HALF\u将0.745四舍五入到0.75?
我试了以下方法Java 如何使用BigDecimal.round\u HALF\u将0.745四舍五入到0.75?,java,bigdecimal,rounding,Java,Bigdecimal,Rounding,我试了以下方法 double doubleVal = 1.745; double doubleVal1 = 0.745; BigDecimal bdTest = new BigDecimal( doubleVal); BigDecimal bdTest1 = new BigDecimal( doubleVal1 ); bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP); bdTest1 = bdTes
double doubleVal = 1.745;
double doubleVal1 = 0.745;
BigDecimal bdTest = new BigDecimal( doubleVal);
BigDecimal bdTest1 = new BigDecimal( doubleVal1 );
bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bdTest:"+bdTest); //1.75
System.out.println("bdTest1:"+bdTest1);//0.74 problemmmm ????????????
但结果很奇怪。为什么?这可能会给你一个错误的提示
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal bdTest = new BigDecimal(0.745);
BigDecimal bdTest1 = new BigDecimal("0.745");
bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("bdTest:" + bdTest); // prints "bdTest:0.74"
System.out.println("bdTest1:" + bdTest1); // prints "bdTest:0.75"
}
}
问题是,您的输入(adouble x=0.745;
)不能精确表示0.745。它实际上保存了一个略低的值。对于大小数
,这已经低于0.745,所以它四舍五入
尽量不要使用
BigDecimal(double/float)
构造函数。永远不要从float或double构造BigDecimal。从整数或字符串构造它们。浮动和加倍松散精度
此代码按预期工作(我刚刚将类型从double更改为String):
产出:
1.74500000000000010658141036401502788066864013671875
0.74499999999999999555910790149937383830547332763671875
这显示了两个双精度的实际值,并解释了得到的结果。正如其他人所指出的,不要使用double构造函数(除了您希望看到double的实际值的特定情况)
有关双精度的更多信息:
double
double doubleVal = 1.745;
double doubleVal2 = 0.745;
doubleVal = Math.round(doubleVal * 100 + 0.005) / 100.0;
doubleVal2 = Math.round(doubleVal2 * 100 + 0.005) / 100.0;
System.out.println("bdTest: " + doubleVal); //1.75
System.out.println("bdTest1: " + doubleVal2);//0.75
或者只是
double doubleVal = 1.745;
double doubleVal2 = 0.745;
System.out.printf("bdTest: %.2f%n", doubleVal);
System.out.printf("bdTest1: %.2f%n", doubleVal2);
都是印刷品
bdTest: 1.75
bdTest1: 0.75
我更喜欢让代码尽可能简单
正如@mshutov所指出的,您需要再添加一点,以确保半个值总是四舍五入。这是因为像
265.335
这样的数字比它们显示的要小一些。使用BigDecimal.valueOf(double d)
而不是新的BigDecimal(double d)
。最后一个具有浮点和双精度误差。可提供多种选项,例如:
Double d= 123.12;
BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64); // b = 123.1200000
b = b.setScale(2, BigDecimal.ROUND_HALF_UP); // b = 123.12
BigDecimal b1 =new BigDecimal(collectionFileData.getAmount(), MathContext.DECIMAL64).setScale(2, BigDecimal.ROUND_HALF_UP) // b1= 123.12
d = (double) Math.round(d * 100) / 100;
BigDecimal b2 = new BigDecimal(d.toString()); // b2= 123.12
如果使用
BigDecimal.valueOf(double)
,这是一种静态工厂方法,优于构造函数(在javadocs中有说明),使用BigDecimal bdTest=BigDecimal.valueOf(1.745),则无需使用字符串即可正常工作;BigDecimal bdTest1=BigDecimal.valueOf(0.745)代码>给出了相同的结果(0.75)@JoshuaGoldberg你不是说BigDecimal.valueOf(“0.745”)代码>而不是BigDecimal.valueOf(1.745)代码>。。。可能不是,没有这样的BigDecimal.valueOf(String)
:-/Yes,注释的关键是缺少引号。从BigDec.valueOf(double)
的javadoc中可以看出:“注意:这通常是将double(或float)转换为BigDecimal的首选方法,因为返回的值等于使用double.toString(double)的结果构造BigDecimal的结果。”如果我的BigDecimal
是从Spring导入的@ConfigurationProperties
?我无法控制它是如何从application.yml
构造的,它假定已经以字符串提供了值,但仍然以相同的舍入问题结束。您可能会得到意外的结果。例如:Math.round(265.335*100)/100.0!=265.34见对的评论
bdTest: 1.75
bdTest1: 0.75
Double d= 123.12;
BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64); // b = 123.1200000
b = b.setScale(2, BigDecimal.ROUND_HALF_UP); // b = 123.12
BigDecimal b1 =new BigDecimal(collectionFileData.getAmount(), MathContext.DECIMAL64).setScale(2, BigDecimal.ROUND_HALF_UP) // b1= 123.12
d = (double) Math.round(d * 100) / 100;
BigDecimal b2 = new BigDecimal(d.toString()); // b2= 123.12