Source: https://urlify.cn/naiEva

We all know that floating-point variables will lose precision when performing calculations. The following piece of 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

It can be seen that when performing floating-point arithmetic in Java, there will be a problem of loss of precision. Then if we calculate the price of goods, there will be problems. It is very likely that we have 0.06 yuan in our hands, but we cannot buy a 0.05 yuan and a 0.01 yuan product. Because as shown above, the sum of the two of them is 0.060000000000000005. This is undoubtedly a very serious problem, especially when the concurrency of e-commerce websites increases, the problems that arise will be huge. It may result in failure to place an order or problems with 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 digits.

Constructor:

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

function:

Method description add(BigDecimal) Add the values in the BigDecimal object, and then return this object. subtract(BigDecimal) Subtract the value in the BigDecimal object, and then return this object. multiply(BigDecimal) Multiply the values in the BigDecimal object, and then return this object. divide(BigDecimal) Divide the value in the BigDecimal object, and then return this object. toString() Converts the numeric value of the BigDecimal object into a string. doubleValue() returns the value in the BigDecimal object as a double-precision number. floatValue() returns the value in the BigDecimal object as a single-precision number. 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 general numeric types, for example, double cannot accurately represent numbers with more than 16 bits.

When we use BigDecimal, it makes sense to use its BigDecimal(String) constructor to create objects. Others, such as BigDecimal b = new BigDecimal(1), still have the problem of 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 BigDecimal is even more excessive. But when using BigDecimal's BigDecimal(String) constructor variables, there is no such problem. The reason is contained in the principles of computer composition, and their coding determines this result. Long can accurately store 19 digits, while double can only be prepared to store 16 digits. Because double has exp bits, it can store more than 16 digits, but it needs to be at the cost of low-order imprecision. If you need accurate storage of more than 19 digits, you must use BigInteger to save, of course, some performance will be sacrificed. Therefore, when we generally use BigDecimal to solve the problem of loss of precision in commercial operations, we must use it to construct a constructor whose parameter is a String type when declaring a BigDecimal object.

At the same time, this principle is also mentioned in Effective Java and MySQL Must Know Must Know. Float and double can only be used for scientific and engineering calculations. We want to use BigDecimal in business computing.

And we officially gave instructions from the comments of the source code. The following is a part of the annotations on the constructor of the double type parameter of the 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 also said very clearly that it can only calculate infinitely close to this number, but it cannot be accurate to this number. The second paragraph says that if you want to calculate this value accurately, you need to convert the double type parameter to the String type. And use the construction method BigDecimal (String) to construct. To get the results.

In addition, what BigDecimal creates is an object. We cannot use traditional arithmetic operators such as +, -, *,/to directly perform mathematical operations on the object, but must call its corresponding method. The parameter in the method must also be an object of BigDecimal, as can be seen from the API we listed just now.

In the general development process, the data stored in our database are of float and double types. It is very inconvenient to perform constant transformations when performing calculations. Here I wrote 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 off return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);//Deal with inexhaustible division } }

This utility class provides basic addition, subtraction, multiplication, and division operations of the double type. Just call it directly.

Recently, I organize personal study notes into a book and share them in PDF. Follow me, reply to the following code, you can get the Baidu disk address, and get it without routines! • 001: "Java Concurrency and High Concurrency Solutions" study notes; • 002: "Deep JVM Kernel-Principles, Diagnosis and Optimization" study notes; • 003: "Java Interview Collection" • 004: "Docker Open Source Book" • 005: "Kubernetes Open Source Book" • 006: "DDD Crash Course (Domain Driven Design Crash Course)" • 007:

All• 008:Add technical discussion group

Reference: https://cloud.tencent.com/developer/article/1596089 How much do you know about the BigDecimal class in Java? -Cloud + Community-Tencent Cloud