简体   繁体   English

大数的十进制小数位数

[英]BigDecimal scale for large numbers

I'm trying to understand the scale for a BigDecimal but it acts weird and I can't understand why. 我正在尝试了解BigDecimal的比例,但是它的行为很奇怪,我不明白为什么。 Here's a couple of examples: 这里有几个例子:

Double d = new Double(1000000d);
int scale = new BigDecimal(d.toString()).scale();

The scale in this example will be 1 which is correct to me. 在此示例中,小数位数为1,对我来说是正确的。 The result of d.toString() is "1000000.0". d.toString()的结果为“ 1000000.0”。

Double d = new Double(10000000d);
int scale = new BigDecimal(d.toString)).scale();

The scale in this example will be -6. 在此示例中,小数位数为-6。 Can anyone explain why? 谁能解释为什么? The result of d.toString() is "1.0E7". d.toString()的结果为“ 1.0E7”。

I thought the number of digits caused this but if I go: 我以为是数字造成的,但是如果我去:

Double d = new Double(11111111d);
int scale = new BigDecimal(d.toString()).scale();

Expected a scale of -8 but suddenly it's 0. The result of d.toString() is "1.1111111E7". 预期小数位数为-8,但突然为0。d.toString()的结果为“ 1.1111111E7”。

These different scales make no sense to me after reading the Javadoc of scale(): 在阅读scale()的Javadoc之后,这些不同的比例对我来说毫无意义:

Returns the scale of this BigDecimal. 返回此BigDecimal的小数位数。 If zero or positive, the scale is the number of digits to the right of the decimal point. 如果为零或正数,则小数位数是小数点右边的位数。 If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. 如果为负,则数字的未标度值将乘以十,即标度取反的幂。 For example, a scale of -3 means the unscaled value is multiplied by 1000. 例如,小数位数为-3表示未缩放的值乘以1000。

I'd very much appreciate an explanation how BigDecimal behaves when the numbers are large. 我非常感谢解释当数字很大时BigDecimal的行为。

Thanks in advance! 提前致谢!

The scale you got is the number of decimals with some significance : 您得到的小数位数是具有一定意义的小数位数:

  • 1000000d -> 1000000.0 -> 0: the numbers at the right of the dot have no significance, the result is 0; 1000000d-> 1000000.0-> 0:点右边的数字无意义,结果为0;
  • 10000000d -> 1.0E7 -> -6: the numbers at the right of the dot have significance, as if you denormalize the power by ten you get the 6 zeros; 10000000d-> 1.0E7-> -6:点右边的数字有意义,就好像您将幂归一化十时,您会得到6个零。
  • 11111111d -> 1.1111111E7 -> 0: all the numbers at the right of the dot have significance, denormalizing the power by ten you get more information, so you "can't" normalize the number if you want to keep this information. 11111111d-> 1.1111111E7-> 0:点右边的所有数字都具有重要性,将幂除以10即可归一化,从而获得更多信息,因此,如果要保留此信息,则不能“对”数进行归一化。 This way (the number denormalized), you have 0 numbers at the right of the dot. 这样(数字被规范化),您在点的右边有0个数字。

EDIT 编辑

As commented, the first line is wrong, it must be 1000000d -> 1000000.0 -> 1 . 如注释所述,第一行是错误的,它必须是1000000d -> 1000000.0 -> 1 The reason is that the numbers with exponential have a different behavior (when obtaining the scale) that the formatted numbers. 原因是带指数的数字(格式化后)具有与格式化数字不同的行为。

The value of 1 is due that BigDecimal counts the numbers in the right side of the dot (which in this case is one, a single 0 ), subtract the numbers to drop (in this case there is one, the single 0 ) and add the math precision (by default is one) -> result = 1. 1的原因是BigDecimal对点右侧的数字进行计数(在这种情况下为1,为单个0 ),减去要删除的数字(在这种情况下,为1,则为单个0 ),然后加上数学精度(默认为1)->结果= 1。

You are seeing the behavior your report because you are calling toString() on the decimal provided, which in for some of your examples represents in exponential notation, which is then preserved by BigDecimal when it chooses the scale. 之所以会看到报告的行为,是因为您在提供的小数点上调用了toString() ,在某些示例中, toString()用指数表示法表示,然后BigDecimal在选择小数位时将其保留下来。

If you provide the the double directly to the BigDecimal constructor you consistently get 0. 如果将double直接提供给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

Update: 更新:

scale is is not a useful attribute on its own. scale本身并不是有用的属性。 It must be considered in conjunction with unscaledValue . 必须将其与unscaledValue结合使用。 The represented number is unscaledValue × 10 ^ -scale. 表示的数字为unscaledValue×10 ^ -scale。

That is, 那是,

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

Both d and e are a representation of 1000000 . de都表示1000000 However, e preserves there are 2 trailing zeros (zeros after the decimal point). 但是, e保留有2个尾随零(小数点后为零)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM