BigDecimal java class of common

BigDecimal

Decimal calculation of the loss of accuracy problems

In the computer, all the files are stored in binary, number crunching is calculated using binary, decimal point because there is no computer, so we usually say that floats like float, doubleall computers use the binary analog out, but we the results obtained computer, run the following code is not correct.

double a = 0.1;
double b = 0.3;
System.out.println(b-a);

// 结果为0.19999999999999998

why?
First look at how we convert decimal to binary numbers

Binary fraction 0.1111

第一位1表示十进制1/2
第二位1表示十进制1/4
第三位1表示十进制1/8
第四位1表示十进制1/16
......

So turn decimal binary fraction, the algorithm is multiplied by 2 until a date no decimals. For example, 0.9 represents a binary number

0.9*2=1.8   取整数部分 1
0.8(1.8的小数部分)*2=1.6    取整数部分 1
0.6*2=1.2   取整数部分 1
0.2*2=0.4   取整数部分 0
0.4*2=0.8   取整数部分 0
0.8*2=1.6 取整数部分 1
0.6*2=1.2   取整数部分 0
.........      0.9二进制表示为(从上往下): 1100100100100......

NOTE: The above calculation cycle, and that is * 2 can never eliminate the fractional part, this algorithm will go on infinitely. Obviously, the binary representation of the decimal sometimes impossible accurate. In fact, the reason is very simple, the decimal system can not be expressed exactly 1/3 of it? The same can not be an accurate representation of the binary system 1/10. This also explains why the floating-point subtraction to a "minus endless" precision loss problems.

About BigDecimal

Because the loss of accuracy problems, so the introduction of java BigDecimal class to solve this problem.

BigDecimal an arbitrary precision integer unscaled value and a 32-bit integer scale (Scale) composition. If zero or a positive number, the scale is the number of digits after the decimal point. If negative, the unscaled value is multiplied by the number of negative power of 10 scale. Thus, the value represented by the BigDecimal is (unscaledValue × 10-scale).

BigDecimal function introduction

Constructor

Constructor as follows

We use the parameters for the doubleconstructor to create the object, and print out the code is as follows

BigDecimal b1 =new BigDecimal(0.1);
System.out.println(b1);

//结果为0.1000000000000000055511151231257827021181583404541015625

We look forward to the results of 0.1, but the result was a loss of precision. Is BigDecimal useless it?

When use the following statement BigDecimal, there will be accuracy problems

BigDecimal b = new BigDecimal(0.1);

Recommended usage

BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = BigDecimal.valueOf(0.1);

Using the above method will not go wrong accuracy problems
BigDecimal.valueOf () to view the source code can know, is the use of new BigDecimal ( "0.1") Constructor

JDK description: 1, a certain parameter type unpredictability of the result of a double construction method. One might think that new BigDecimal written in Java (0.1) creates a BigDecimal which is exactly equal to 0.1 (unscaled value is 1, and whose scale is 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 can not be accurately expressed as a double (or, for that matter, can not be expressed as a binary fraction of any finite length). In this way, passed to the constructor is not exactly equal to the value of 0.1 (although this value is equal to the upper surface).

2, on the other hand, String constructor is entirely predictable: Write newBigDecimal ( "0.1") creates a BigDecimal, which is exactly equal to the expected 0.1. Therefore, in contrast, it is generally recommended to use String constructor priority.

3, the source must be used when the double BigDecimal, please note that this configuration provides an accurate conversion method; it does not provide the same results with the following operations: using the Double.toString first (double) method, and then use the BigDecimal (String) construction method, a double into a String. To obtain the results, use static valueOf (double) method.

Common method

  • 1.BigDecimal (String val): constructor, BigDecimal to convert a String type data.
  • 2.BigDecimal (double val): constructor, BigDecimal to convert the double type to type data.
  • 3.BigDecimal (int val): constructor, BigDecimal to convert into an int type data.
  • 4.BigDecimal add (BigDecimal value): an adder, sum of two types of data and BigDecimal.
  • 5.BigDecimal subtract (BigDecimal value): subtraction, difference BigDecimal two types of data.
  • 6.BigDecimal multiply (BigDecimal value): multiplication, Quadrature BigDecimal two types of data.
  • 7.BigDecimal divide (BigDecimal divisor): division, seeking BigDecimal two types of data providers.
  • 8.BigDecimal remainder (BigDecimal divisor): find the remainder, seeking BigDecimal type of data is divided by the divisor.
  • 9.BigDecimal max (BigDecimal value): the maximum number, the maximum BigDecimal find two types of data.
  • 10.BigDecimal min (BigDecimal value): the minimum number, the sum of two types of data BigDecimal minimum.
  • 11.BigDecimal abs (): absolute value, the absolute value of the data request BigDecimal type.
  • 12.BigDecimal negate (): number of contrast, the number of types of data required BigDecimal opposite.

Code demonstrates

        BigDecimal  a=new BigDecimal ("4.5");
        BigDecimal  b=new BigDecimal ("1.5");
        BigDecimal  c=new BigDecimal ("-10.5");
 
        BigDecimal  add_result=a.add(b);
        BigDecimal  subtract_result=a.subtract(b);
        BigDecimal  multiply_result=a.multiply(b);
        BigDecimal  divide_result=a.divide(b);
        BigDecimal  remainder_result=a.remainder(b);
        BigDecimal  max_result=a.max(b);
        BigDecimal  min_result=a.min(b);
        BigDecimal  abs_result=c.abs();
        BigDecimal  negate_result=a.negate();
 
        Log.d("TAG","4.5+1.5="+add_result);
        Log.d("TAG","4.5-1.5="+subtract_result);
        Log.d("TAG","4.5*1.5="+multiply_result);
        Log.d("TAG","4.5/1.5="+divide_result);
        Log.d("TAG","4.5/1.5余数="+remainder_result);
        Log.d("TAG","4.5和1.5最大数="+max_result);
        Log.d("TAG","4.5和1.5最小数="+min_result);
        Log.d("TAG","-10.5的绝对值="+abs_result);
        Log.d("TAG","4.5的相反数="+negate_result);

Results

4.5+1.5=6.0
4.5-1.5=3.0
4.5*1.5=6.75
4.5/1.5=3
4.5/1.5余数=0.0
4.5和1.5最大数=4.5
4.5和1.5最小数=1.5
-10.5的绝对值=10.5
4.5的相反数=-4.5

BigDecimal is immutable (immutable), and during every step of the operation, will have a new object, so the value of the operation do, never to be saved when arithmetic operations.

BigDecimalWith scale()representation of decimal places, such as:

BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.4500");
BigDecimal d3 = new BigDecimal("1234500");
System.out.println(d1.scale()); // 2,两位小数
System.out.println(d2.scale()); // 4
System.out.println(d3.scale()); // 0

By BigDecimalthe stripTrailingZeros()method, a BigDecimalformat of an equal, but removed at the end of 0 BigDecimal:

BigDecimal d1 = new BigDecimal("123.4500");
BigDecimal d2 = d1.stripTrailingZeros();
System.out.println(d1.scale()); // 4
System.out.println(d2.scale()); // 2,因为去掉了00

BigDecimal d3 = new BigDecimal("1234500");
BigDecimal d4 = d1.stripTrailingZeros();
System.out.println(d3.scale()); // 0
System.out.println(d4.scale()); // -2

If one BigDecimalof the scale()returns negative, e.g., -2, indicates that the number is an integer, and there are two zeros at the end.

A can BigDecimalthat is provided scale, if the precision is lower than the original value, according to the method specified rounding truncation or directly:

public class Main {
    public static void main(String[] args) {
        BigDecimal d1 = new BigDecimal("123.456789");
        BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568
        BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // 直接截断,123.4567
        System.out.println(d2);
        System.out.println(d3);
    }
}

To BigDecimaldo addition, subtraction, multiplication when precision is not lost, but do division, there are cases can not be divided, then, you must specify the precision and how to cut:

BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("23.456789");
BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入

In comparing the two BigDecimalwhen the values are equal, important to note that the use of equals()the method requires only two BigDecimalequal values, they are also required to scale()be equal:

BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("123.45600");
System.out.println(d1.equals(d2)); // false,因为scale不同
System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2
System.out.println(d1.compareTo(d2)); // 0

Must use the compareTo()method to compare, which returns a negative, respectively, according to the size of two values, 0 and positive, respectively, less than, greater than, and equal.

Always used compareTo()to compare two BigDecimalvalues, do not use equals()!
If you look at BigDecimalthe source code can be found, is actually a BigDecimalby a BigIntegerand a scaleto indicate, that BigIntegerrepresents a complete integer, and scalerepresents the number of decimal places:

public class BigDecimal extends Number implements Comparable<BigDecimal> {
    private final BigInteger intVal;
    private final int scale;
}

BigDecimalAlso from Numberinherited, and it is immutable objects.

Source code analysis

Why BigDecimaluse Stringdoes not occur accuracy problems
and now we understand why the use double, float appears the accuracy problems. Now we will look BigDecimalfor String did not accuracy problems

Debug by constructor, we can understand, the BigDecimal underlying data structure is mainly composed of the following four property values.

int scale; //有多少位小数(即小数点后有多少位)
int precision; //总工有多少位数字
long intCompact; //字符串去掉小数点后,转为long的值,只有当传的字符串长度小于18时才使用该言
BigInteger intVal; //当传的字符串长度大于等于18时才使用BigInteger表示数字

To new BigDecimal("12.12")an example

scale值为2
precision值为4
intCompact值为1212
intVal值为空。
之所以为空是因为字符串长度没有超18位,所以不启用BigInteger表示

In fact, we see this in turn should understand, BigDecimal or the String into a long BigInteger be calculated.

valueOf (doubleval) Method

valueOfActually call the appropriate wrapper class toStringmethod and then create a String object constructor parameters BigDecimal.

add(BigDecimal augend)方法

     

    public BigDecimal add(BigDecimal augend) {
          long xs = this.intCompact; //整型数字表示的BigDecimal,例a的intCompact值为122
          long ys = augend.intCompact;//同上
          BigInteger fst = (this.intCompact != INFLATED) ? null : this.intVal;//初始化BigInteger的值,intVal为BigDecimal的一个BigInteger类型的属性
          BigInteger snd = (augend.intCompact != INFLATED) ? null : augend.intVal;
          int rscale = this.scale;//小数位数
          long sdiff = (long) rscale - augend.scale;//小数位数之差
          if (sdiff != 0) {//取小数位数多的为结果的小数位数
              if (sdiff < 0) {
                 int raise = checkScale(-sdiff);
                 rscale = augend.scale;
                 if (xs == INFLATED ||
                     (xs = longMultiplyPowerTen(xs, raise)) == INFLATED)
                     fst = bigMultiplyPowerTen(raise);
               } else {
                   int raise = augend.checkScale(sdiff);
                   if (ys == INFLATED || (ys = longMultiplyPowerTen(ys, raise)) == INFLATED)
                      snd = augend.bigMultiplyPowerTen(raise);
               }
          }
          if (xs != INFLATED && ys != INFLATED) {
              long sum = xs + ys;
              if ((((sum ^ xs) & (sum ^ ys))) >= 0L)//判断有无溢出
                 return BigDecimal.valueOf(sum, rscale);//返回使用BigDecimal的静态工厂方法得到的BigDecimal实例
           }
           if (fst == null)
               fst = BigInteger.valueOf(xs);//BigInteger的静态工厂方法
           if (snd == null)
               snd = BigInteger.valueOf(ys);
           BigInteger sum = fst.add(snd);
           return (fst.signum == snd.signum) ? new BigDecimal(sum, INFLATED, rscale, 0) :
              new BigDecimal(sum, compactValFor(sum), rscale, 0);//返回通过其他构造方法得到的BigDecimal对象
      }

These are just the addition of the source code analysis, subtraction, multiplication and division in fact eventually returns a new BigDecimal object because BigInteger and BigDecimal is immutable (the immutable), and during each step of the operation, will produce a new object, Therefore a.add (b); while doing addition operations, but does not keep a value added operation, the correct usage should be a = a.add (b);

to sum up

(1) business computing use BigDecimal.

(2) make use of parameters of type String constructor.

(3) BigDecimal is immutable (the immutable), and during each step of the operation, will produce a new object, so to add and subtract a value of ten million to be saved when the multiplication and division operations.

(4) We often easy to overlook some of the implementation details of the underlying JDK, resulting in an error, we need to pay more attention.

Reference:
Zhao Yongwen ,
jackiehff ,
the official website of Liao Xuefeng .

Guess you like

Origin www.cnblogs.com/elichen/p/11608352.html
Recommended