我正在尝试创建一个始终具有固定最大分数的BigDecimal
类。
但是当打印这个数字时,它不会被切割成我在比例中定义的分数。为什么呢?
class MyDecimal extends BigDecimal {
public MyDecimal(double val) {
super(val);
setScale(4, RoundingMode.HALF_UP);
}
}
Sysout(new MyDecimal(0.0001));
//0.000100000000000000008180305391403130954586231382563710212707519531254
答案 0 :(得分:4)
BigDecimal是不可变的,不应该扩展。 setScale()
不会修改BigDecimal实例。它返回BigDecimal实例的副本,并修改了比例(与BigDecimal的每个其他“变异”方法一样,因为它是不可变的)。因此调用它并忽略返回的值是没用的。
不是扩展BigDecimal,而是创建工厂方法:
public static BigDecimal createWithScale4(double d) {
BigDecimal temp = new BigDecimal(d);
return temp.setScale(4);
}
答案 1 :(得分:2)
问题在于您将输入作为双精度输入。这是来自javadoc:
这个构造函数的结果可能有些不可预测。一 可能会假设在Java中编写新的BigDecimal(0.1)会创建一个 BigDecimal正好等于0.1(未缩放的值为1,带有 比例为1),但它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为double(或者为此) 重要的是,作为任何有限长度的二进制分数)。因此,价值 传入构造函数的不完全等于 0.1,尽管出现
由于您使用的是double
,因此将其存储为浮点数,将不存储为精度数。然后,它将该非精度浮点数转换为精度BigDecimal
,然后将其作为精确数字输出。但是,如果输入是String
,则它会起作用,因为String
只是文本,并将字符串直接转换为BigDecimal
。请参阅here:
从(标量)double创建一个大小数很简单:
bd = new BigDecimal(1.0);
要从Double获取BigDecimal,请获取它 doubleValue()首先。
然而,使用字符串构造函数是个好主意:
bd = new BigDecimal(“1.5”);
如果您不这样做,那么您将获得以下内容,
bd = new BigDecimal(1.5);
bd.toString(); // => 0.1499999999999999944488848768742172978818416595458984375
所以这样做:
Sysout(new MyDecimal("0.0001"));
另外,正如@JBNizet指出的那样,你正在扩展一个不可变对象,BigDecimal
。您忽略了设置比例的返回值。这可以通过使用如下方法来改变:
public static BigDecimal createBigDecimal(String s) {
BigDecimal bigdeci = new BigDecimal(s);
return bigdeci.setScale(4);
}
答案 2 :(得分:1)
问题是你将参数传递为double而不是字符串。在参数到达大十进制之前,它已经被转换为二进制形式以存储为double,这引入了一个小错误(它等同于尝试将1/3作为小数写入并获得0.3333333333;它将不会相当正确,除非你有无限的精确度。)
相反,请尝试:
Sysout((new BigDecimal("0.0001")).setScale(4,RoundingMode.HALF_UP));