我试图理解 BigDecimal 的比例,但它表现得很奇怪,我不明白为什么。以下是几个示例:
Double d = new Double(1000000d);
int scale = new BigDecimal(d.toString()).scale();
此示例中的刻度将为 1,这对我来说是正确的。 d.toString() 的结果是 "1000000.0"。
Double d = new Double(10000000d);
int scale = new BigDecimal(d.toString)).scale();
此示例中的刻度将为 -6。谁能解释为什么? d.toString() 的结果是 "1.0E7"。
我认为是位数导致了这种情况,但如果我去:
Double d = new Double(11111111d);
int scale = new BigDecimal(d.toString()).scale();
预计比例为 -8,但突然变为 0。 d.toString() 的结果是 "1.1111111E7"。
这些不同的尺度在阅读了scale()的Javadoc之后对我来说毫无意义:
返回此大十进制的比例。如果为零或正数,则小数位数为小数点右侧的位数。如果为负数,则数字的未标度值乘以 10 的幂,等于刻度的否定幂。例如,小数位数为 -3 表示未缩放的值乘以 1000。
我非常感谢解释一下 BigDecimal 在数字很大时的行为。
提前感谢!
你得到的刻度是具有一定意义的小数位数:
- 1000000d -> 1000000.0 -> 0:点右侧的数字没有意义,结果为 0;
- 10000000d -> 1.0E7 -> -6:点右侧的数字具有显著性,就像您将幂非正规化 10 得到 6 个零;
- 11111111d -> 1.1111111E7 -> 0:点右侧的所有数字都具有显著性,将幂非规范化 10 你会得到更多信息,所以如果你想保留这些信息,你"不能"对数字进行归一化。这样(非规范化的数字),点的右侧有 0 个数字。
编辑
如前所述,第一行是错误的,必须1000000d -> 1000000.0 -> 1
.原因是具有指数的数字与格式化数字具有不同的行为(在获取比例时)。
1
的值是由于BigDecimal
计算点右侧的数字(在本例中为 1,单个0
),减去要丢弃的数字(在本例中为一个,单个0
)并添加数学精度(默认为 1)->结果 = 1。
您看到的是报表的行为,因为您正在调用toString()
提供的十进制,对于某些示例,小数以指数表示法表示,然后在选择比例时由BigDecimal
保留。
如果将双精度值直接提供给BigDecimal
构造函数,则始终得到 0。
new Double(1000000d).toString() //1.0E7
Double d = new Double(1000000d);
int scale = new BigDecimal(d).scale(); //0
Double d = new Double(10000000d);
int scale = new BigDecimal(d).scale(); //0
Double d = new Double(11111111d);
int scale = new BigDecimal(d).scale(); //0
更新:
scale
本身并不是一个有用的属性。 必须结合unscaledValue
考虑。 表示的数字是未缩放的值× 10 ^ -scale。
那是
BigDecimal d = new BigDecimal(1000000d)
BigDecimal e = d.setScale(2)
int dScale = d.scale() //0
int dUnscaled = d.unscaledValue() //1000000
int eScale = e.scale() //2
int eUnscaled = e.unscaledValue() //100000000
d
和e
都是1000000
的表示。 但是,e
保留有 2 个尾随零(小数点后的零)。
d.toString() //1000000
e.toString() //1000000.00