怎么使用BigDecimal保证小数运算的精度

问题:

在计算机二进制存储小数中,存在精度丢失的现象
在这里插入图片描述对小数进行运算时,结果会失真
在这里插入图片描述

原因:

小数在计算机中存储的方式造成的。
其存储方式是对小数点后的数乘2,大于1的记录为1,小于1记录为零,知道小数点后的数都为零,如下所示,0.1按照这种方式是乘不尽的。

0.1 * 2 = 0.2     -----0
0.2 * 2 = 0.4     -----0
0.4 * 2 = 0.8     -----0
0.8 * 2 = 1.6     -----1
0.6 * 2 = 1.2     -----1
0.2 * 2 = 0.4     -----0
.
.
.
//你懂的 0.0001100110011001100110011001100110011001100110011001101

解决方法:

使用BigDecimal的BigDecimal(String val)这个构造器来创建对象。通过这个构造器生成的对象进行数值运算可以保证结果的精度。那么他是怎么实现的?

public BigDecimal(String val) {
        this(val.toCharArray(), 0, val.length());
    }

下面是这个构造器的文档。简而言之,就是把string表示成一个长度为二的字符数组,如1.200 表示成[12,3],数组第一位表示整数,数值大小,第二位表示小数个数。然后根据这个字符数组构造一个具有准确精度的小数。

Translates the string representation of a BigDecimal into a BigDecimal. The string representation consists of an optional sign, '+' ( '\u002B') or '-' ('\u002D'), followed by a sequence of zero or more decimal digits ("the integer"), optionally followed by a fraction, optionally followed by an exponent.
The fraction consists of a decimal point followed by zero or more decimal digits. The string must contain at least one digit in either the integer or the fraction. The number formed by the sign, the integer and the fraction is referred to as the significand.
The exponent consists of the character 'e' ('\u0065') or 'E' ('\u0045') followed by one or more decimal digits. The value of the exponent must lie between -Integer.MAX_VALUE (Integer.MIN_VALUE+1) and Integer.MAX_VALUE, inclusive.
More formally, the strings this constructor accepts are described by the following grammar:
BigDecimalString:
Signopt Significand Exponentopt
Sign:
+
-
Significand:
IntegerPart . FractionPartopt
. FractionPart
IntegerPart
IntegerPart:
Digits
FractionPart:
Digits
Exponent:
ExponentIndicator SignedInteger
ExponentIndicator:
e
E
SignedInteger:
Signopt Digits
Digits:
Digit
Digits Digit
Digit:
any character for which Character.isDigit returns true, including 0, 1, 2 ...
The scale of the returned BigDecimal will be the number of digits in the fraction, or zero if the string contains no decimal point, subject to adjustment for any exponent; if the string contains an exponent, the exponent is subtracted from the scale. The value of the resulting scale must lie between Integer.MIN_VALUE and Integer.MAX_VALUE, inclusive.
The character-to-digit mapping is provided by Character.digit set to convert to radix 10. The String may not contain any extraneous characters (whitespace, for example).
Examples: The value of the returned BigDecimal is equal to significand × 10 exponent. For each string on the left, the resulting representation [BigInteger, scale] is shown on the right.
       "0"            [0,0]
       "0.00"         [0,2]
       "123"          [123,0]
       "-123"         [-123,0]
       "1.23E3"       [123,-1]
       "1.23E+3"      [123,-1]
       "12.3E+7"      [123,-6]
       "12.0"         [120,1]
       "12.3"         [123,1]
       "0.00123"      [123,5]
       "-1.23E-12"    [-123,14]
       "1234.5E-4"    [12345,5]
       "0E+7"         [0,-7]
       "-0"           [0,0]
       
Note: For values other than float and double NaN and ±Infinity, this constructor is compatible with the values returned by Float.toString and Double.toString. This is generally the preferred way to convert a float or double into a BigDecimal, as it doesn't suffer from the unpredictability of the BigDecimal(double) constructor.
Params:
val – String representation of BigDecimal.
Throws:
NumberFormatException – if val is not a valid representation of a BigDecimal.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值