If BigDecimal is not used properly, the boss's loss will still be deducted from your salary

Yunqi information:[ Click to see more industry information]
Here you can find the first-hand cloud information of different industries. What are you waiting for? Come on!

We have basically formed a common sense that we need to use BigDecimal instead of others where money is needed, and we all know that floating-point variables will lose precision when calculating.

So, do you know that BigDecimal also loses precision? Is there anything worth exploring behind the use of BigDecimal? Today, let me tell you, know what it is, and know why it is.

Here is a code:

System.out.println(0.05 + 0.01);  
System.out.println(1.0 - 0.42);  
System.out.println(4.015 * 100);  
System.out.println(123.3 / 100);  

Output:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

You can see that when floating-point calculation is carried out in Java, there will be the problem of losing precision. Then if we calculate the price of goods, there will be problems.
It is likely that we have 0.06 yuan in hand, but we can't buy a 0.05 yuan and a 0.01 yuan commodity.

Because as shown above, the sum of the two of them is 0.060000000000000005.

This is undoubtedly a very serious problem, especially when the concurrent amount of e-commerce websites goes up, the problem will be huge. This may result in the inability to place an order or problems with the reconciliation. So next we can use the BigDecimal class in Java to solve this kind of problem.

Popularize:
The precision of float in Java is 6-7 significant digits. The precision of double is 15-16 bits.

API
Constructor:

Constructor description
 BigDecimal(int) creates an object with the integer value specified by the parameter.
BigDecimal(double) creates an object with a double value specified by the parameter.
BigDecimal(long) creates an object with a long integer value specified by the parameter.
BigDecimal(String) creates an object with a string value specified by the parameter.

Function:

Method description
 Add (BigDecimal) adds the values in the BigDecimal object and returns the object.
Subtract (BigDecimal) the value in the BigDecimal object is subtracted, and then the object is returned.
Multiply (BigDecimal) the value in the BigDecimal object is multiplied, and then the object is returned.
Divide (BigDecimal) divides the values in the BigDecimal object and returns the object.
toString() converts the value of the BigDecimal object to a string.
doubleValue() returns the value in the BigDecimal object as a double.
floatValue() returns the value in the BigDecimal object as a single precision.
longValue() returns the value in the BigDecimal object as a long integer.
intValue() returns the value in the BigDecimal object as an integer.

Due to the general numerical type, for example, double can not accurately represent more than 16 digits.

BigDecimal precision is also lost

When we use BigDecimal, it makes sense to use its BigDecimal(String) constructor to create objects. Other problems, such as BigDecimal b = new BigDecimal(1), still cause the loss of precision. The following code:

BigDecimal a = new BigDecimal(1.01);
BigDecimal b = new BigDecimal(1.02);
BigDecimal c = new BigDecimal("1.01");
BigDecimal d = new BigDecimal("1.02");
System.out.println(a.add(b));
System.out.println(c.add(d));

Output:
2.0300000000000000266453525910037569701671600341796875
2.03

It can be seen that the loss of precision of BigDecimal is more obvious. However, the variable using BigDecimal(String) constructor of BigDecimal does not have this problem during the operation.

The reason lies in the principle of computer composition. Their coding determines such a result.

long can store exactly 19 digits, while double can only store 16 digits.

Because double has exp bits, it can store more than 16 digits, but at the cost of low-level imprecision. If you need more than 19 digits of accurate storage, you must use BigInteger to save, which will certainly sacrifice some performance.

So we usually use BigDecimal to solve the problem of losing precision in commercial operation. When declaring a BigDecimal object, we must use it to construct a constructor of type String.

At the same time, this principle is also mentioned in Effective Java and MySQL must know. float and double can only be used for scientific calculation and engineering calculation. We use BigDecimal in business operations.

In addition, we also give an official explanation from the source annotation, as follows is a part of the annotation on the constructor of double type parameter of BigDecimal class:

* The results of this constructor can be somewhat unpredictable.  
     * One might assume that writing {@codenew BigDecimal(0.1)} in  
     * Java creates a {@code BigDecimal} which is exactly equal to  
     * 0.1 (an unscaled value of 1, with a scale of 1), but it is  
     * actually equal to  
     * 0.1000000000000000055511151231257827021181583404541015625.  
     * This is because 0.1 cannot be represented exactly as a  
     * {@codedouble} (or, for that matter, as a binary fraction of  
     * any finite length).  Thus, the value that is being passed  
     * <i>in</i> to the constructor is not exactly equal to 0.1,  
     * appearances notwithstanding.  
       ......  
        * When a {@codedouble} must be used as a source for a  
     * {@code BigDecimal}, note that this constructor provides an  
     * exact conversion; it does not give the same result as  
     * converting the {@codedouble} to a {@code String} using the  
     * {@link Double#toString(double)} method and then using the  
     * {@link #BigDecimal(String)} constructor.  To get that result,  
     * use the {@codestatic} {@link #valueOf(double)} method.  
     * </ol>  
public BigDecimal(double val) {  
    this(val,MathContext.UNLIMITED);  
}  

The first paragraph is also clear that it can only calculate infinite close to this number, but it can not be accurate to this number.
In the second paragraph, if you want to calculate the value accurately, you need to convert the parameter of double type to that of String type. And use BigDecimal(String) to construct. To get results.

Using BigDecimal correctly

In addition, what BigDecimal creates is an object. Instead of using traditional arithmetic operators such as +, -, *, / to perform mathematical operations on its objects directly, we must call its corresponding methods. The parameter in the method must also be the object of BigDecimal, as can be seen from the API listed just now.
In the general development process, the data stored in our database are of float and double types. In the process of taking and taking operations, it needs continuous transformation, which is very inconvenient. Here I write a tool class:

**  
 * @author: Ji YongGuang.  
 * @date: 19:50 2017/12/14.  
 */  
publicclass BigDecimalUtil {  

    private BigDecimalUtil() {  

    }  

    public static BigDecimal add(double v1, double v2) {// v1 + v2  
        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
        return b1.add(b2);  
    }  

    public static BigDecimal sub(double v1, double v2) {  
        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
        return b1.subtract(b2);  
    }  

    public static BigDecimal mul(double v1, double v2) {  
        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
        return b1.multiply(b2);  
    }  

    public static BigDecimal div(double v1, double v2) {  
        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
        // 2 = keep two decimal places ROUND_HALF_UP = round  
        return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);// Dealing with endless situations  
    }  
}  

This utility class provides basic addition, subtraction, multiplication and division operations of double type. Call directly

[yunqi online class] product technology experts share every day!
Course address: https://yqh.aliyun.com/zhibo

Join the community immediately, face to face with experts, and keep abreast of the latest news of the course!
[yunqi online classroom community] https://c.tb.cn/F3.Z8gvnK

Original release time: June 18, 2020
Author: HikariCP
This article comes from:“ Internet architect WeChat official account ”, you can pay attention to“ Internet architect"

Keywords: Java MySQL Database

Added by keiran420 on Thu, 18 Jun 2020 11:53:31 +0300