当与stripTrailingZeros()方法结合使用时,为什么bigDecimal的scale()方法返回负值?

时间:2019-04-04 05:02:48

标签: java android bigdecimal

为了避免类似{{1}的10.0000这样的值,我使用了BigDecimal方法,该方法返回值10而不是预期的10.0000。现在,小数位数10应该为0,因为对于零或正值,小数位数是小数点右边的位数。但是,情况并非如此,因为它返回-1。

stripTrailingZeros()

以上代码返回时,值10和Log.d("click", BigDecimal("10").toPlainString()) // return 10 Log.d("click", BigDecimal("10").stripTrailingZeros().toPlainString()) // return 10 对其值没有影响。

stripTrailingZeros()

但是这些值的小数位不同,因为它返回0和-1,并且返回

Log.d("click", BigDecimal("10").scale().toString())  // return 0
Log.d("click", BigDecimal("10").stripTrailingZeros().scale().toString()) // return -1

有什么办法可以得到预期的结果?有人可以解释为什么Log.d("click", BigDecimal("100").stripTrailingZeros().scale().toString()) // return -2 Log.d("click", BigDecimal("1000").stripTrailingZeros().scale().toString()) // return -3 方法返回负值吗?

1 个答案:

答案 0 :(得分:0)

那是由于BigDecimal的存储方式。它使用刻度来记住小数位数。

unscaledValue和scale

大十进制可以记住它拥有的小数位数(放在小数点分隔符后面)。为此,将它们存储为两个值:

  • 一个 unscaledValue (通常是BigInteger,但对于较小的值也可能是一个长整数),其中包含(有效)数字和
  • 标度 的10的幂乘以 unscaledValue 以获得标称值,即一种负指数)。

示例:值 1.0 存储为UnscaledValue(我将其称为UV),其值为10,小数位为1( 10 x 10 -1 )。值 3.000 存储为3000的UV,刻度为3( 3000 x 10 -3 ), 12.34 如UV = 1234和scale = 2(即 1234 x 10 -2 ),依此类推。

您的值 10 存储为UV = 10和小数位数= 0(简写:UV = 10,s = 0)。但是,如果您删除尾随零,则将 1.000 (UV = 1000,S = 3),您从UV剥离了试验零点并相应地调整了比例,因此它变为(UV = 1,S = 0):UV损失了3个零点,比例调整为0。

也可以使用负标度,以表示()的10次方。值 2e20 存储为UV = 2, s = -20( 2 x 10 20 ),而不是UV = 200000000000000000000,s = 0。这样可以节省大量空间。同样, 2.00e20 存储为UV = 200,s = -18或 200 x 10 18

这就是为什么删除尾随零时, 10 变为UV = 1,s = -1( 1 x 10 1 ) ,而不是UV = 10,而是s = 0( 10 x 10 0 )。而 6000 (UV = 6000,s = 0)变为 6E + 3 (UV = 6,s = -3; 6 x 10 3 < / sup> )。

设置比例尺

但是您可以在不更改标称值的情况下轻松将比例尺设置回0。如果比例为负,则不会四舍五入。

BigDecimal b1 = new BigDecimal("10.000"); // UV=10000, s=3, 10000 x 10**-3
System.out.println(b1);
b1 = b1.stripTrailingZeros();             // UV=1, s=-1, *all* trailing zeros removed,
                                          // as desired: 10000 --> 1
System.out.println(b1);
b1 = b1.setScale(0);                      // UV=10, s=0
System.out.println(b1);

输出:

10.000
1E+1
10

因此,要仅除去尾随的十进制零,请执行以下操作:

b1 = b1.stripTrailingZeros();
if (b1.scale() < 0)
  b1 = b1.setScale(0);