【问题标题】:BigDecimal scale for large numbers大数的 BigDecimal 小数位数
【发布时间】:2017-07-26 11:17:15
【问题描述】:

我试图了解 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 后,这些不同的比例对我来说毫无意义:

返回此 BigDecimal 的小数位数。如果为零或正数,则刻度是小数点右侧的位数。如果为负数,则将数字的未缩放值乘以 10 的负数次方。例如,-3 的比例表示未缩放的值乘以 1000。

我非常感谢您解释 BigDecimal 在数字很大时的行为方式。

提前致谢!

【问题讨论】:

  • 在将d.toString() 的值传递给new BigDecimal 之前检查它的值。它可能没有您认为的价值。
  • 为示例添加了 d.toString() 的结果,但对我没有多大帮助。

标签: java math bigdecimal


【解决方案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 一起考虑。表示的数字是 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

de 都是 1000000 的表示形式。但是,e 保留有 2 个尾随零(小数点后的零)。

d.toString() //1000000
e.toString() //1000000.00

【讨论】:

  • 谢谢!当我初始化我的 BigDecimals 时,我将使用双精度数。
【解决方案2】:

你得到的刻度是小数位数有一定意义

  • 1000000d -> 1000000.0 -> 0:点右边的数字没有意义,结果为0;
  • 10000000d -> 1.0E7 -> -6:点右边的数字是有意义的,就好像你将幂反规格化 10 会得到 6 个零;
  • 11111111d -> 1.1111111E7 -> 0:点右侧的所有数字都有意义,将幂非规格化十你会得到更多信息,所以如果你想保留它,你“不能”标准化数字信息。这样(数字非规范化),点右侧有 0 个数字。

编辑

正如评论,第一行是错误的,它必须是1000000d -> 1000000.0 -> 1。原因是具有指数的数字与格式化数字具有不同的行为(在获取比例时)。

1 的值是由于 BigDecimal 计算点右侧的数字(在本例中为一个,单个 0),减去要删除的数字(在本例中为一,单个0) 并添加数学精度(默认为一)-> 结果 = 1。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 2016-07-19
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多