May 31, 2021 Article blog
This article comes from the public number: Hollis Author: Hollis
BigDecimal
which many people should have heard of and knows how to use it, is a type provided in the
java.math
package that can be used for precise operations.
Many people know that in scenarios such as amount representation, amount calculation, and so on, you can't use types like
double
float
but you can use a better
BigDecimal
that supports precision.
As a result,
BigDecimal
is used very frequently in many payments, e-commerce, finance, and more.
And it has to be said that this is a very good use of the class, its internal comes with a lot of methods, such as addition, subtraction, multiply, divided and other methods can be called directly.
In addition to the need to represent numbers in
BigDecimal
and perform numerical operations, equal judgment of numbers is often required in code.
This knowledge point on
BigDecimal
equivalent judgment is also explained in the latest edition of Alibaba Java Development Manual:
So why is there such a requirement? What's the thinking behind it?
In fact, in my previous CodeReview, I've seen low-level errors like this:
if(bigDecimal == bigDecimal1){
// 两个数相等
}
This error, believed to be a clever reader, can be seen at a glance, because BigDecimal is an object, so it is not available to determine whether the values of the two numbers are equal.
The above questions, after some experience, can still be avoided, but smart readers, look at the following line of code, do you think he has a problem:
if(bigDecimal.equals(bigDecimal1)){
// 两个数相等
}
Can clearly tell you that the above writing, may get the result is not the same as you expected!
Let's do an experiment and run the following code:
BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));
BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));
BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));
The above code, the output is:
true
true
false
From the code example above, we found that when comparing 1 and 1.0 using
BigDecimal
equals
method, sometimes true (when bigDecimal is defined with int, double), and sometimes false (when String is used to define BigDecimal).
So why is this happening, let's start with
BigDecimal
equals
approach.
The reasons are actually explained in BigDecimal's JavaDoc:
Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method)
Presumably, the equals method is not the same as the composreTo method, which compares two parts, value and scale
The corresponding code is as follows:
Therefore, the accuracy of the two
BigDecimal
objects defined by our code above (bigDecimal4 and bigDecimal5) is different, so the result of the
equals
comparison is
false
Trying to
debug
the code, in the process of
debug
we can also see that the accuracy of
bigDecimal4
is 0, while the accuracy of
bigDecimal5
is 1.
Here, we've probably explained that equals compare the
equals
of
bigDecimal4
and
bigDecimal5
to false because of the different precision.
So why is the accuracy different?
Why are
bigDecimal2
and
bigDecimal3
with the same precision (when bigDecimal is defined using int, double), and
bigDecimal4
bigDecimal5
are different (when BigDecimal is defined using String)?
This relates to the accuracy of
BigDecimal
which is actually more complex, because it is not the focus of this article, this is a brief introduction.
If you are interested, let's talk about it separately.
First, BigDecimal has four construction methods:
In the above four methods, the accuracy of the
BigDecimal
created is different.
First of all, the simplest are BigDecimal (long) and BigDecimal (int), because it is an integer, so the accuracy is 0:
public BigDecimal(int val) {
this.intCompact = val;
this.scale = 0;
this.intVal = null;
}
public BigDecimal(long val) {
this.intCompact = val;
this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
this.scale = 0;
}
For BigDecimal (double), when we create a BigDecimal (0.1) using new BigDecimal (0.1), the value created is not exactly equal to 0.1, but 0.1000000000555111511512312578270218158340451015625 . T his is because the dole itself represents only an approximation.
So, whether we use
new BigDecimal(0.1)
or new
new BigDecimal(0.10)
his approximation is 0.100 million 0055511151231257827021181583404541015625 This, then his accuracy is the number of digits of this number, that is, 55.
Other floats make the same sense.
In the form
new BigDecimal(1.0)
because he is essentially an integer, the precision of the numbers he creates is 0.
So, because
BigDecimal(1.0)
and
BigDecimal(1.00)
have the same accuracy, when comparing using
equals
method, the result is true.
For
BigDecimal(double)
when we create a BigDecimal ("0.1") using new BigDecimal ("0.1"), the value created is exactly equal to 0.1. T
hen his precision is 1.
If you use new BigDecimal ("0.10000"), the number created is 0.10000, and the accuracy is 5.
So, because BigDecimal ("1.0") and BigDecimal ("1.00") are not as accurate, the result when comparing using the equals method is false.
Earlier, we explained
BigDecimal
equals method, which
equals
not only the values of numbers, but also their accuracy.
Therefore, when we use
equals
method to determine whether two numbers are equal, it is extremely strict.
So, if we just want to tell if the values of the two
BigDecimal
are equal, how do we tell?
The compareTo method is provided in BigDecimal, which allows you to compare the values of only two numbers and return 0 if the two numbers are equal.
BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0000");
System.out.println(bigDecimal4.compareTo(bigDecimal5));
Above code, output:
0
The source code is as follows:
BigDecimal
is a very useful class for representing high-precision numbers, which provides many rich methods.
However, his equals method needs to be used with caution because when comparing, he not only
equals
the values of two numbers, but also their accuracy, as long as one of the two factors is not equal, then the result is false.
If the reader wants to compare the values of the two
BigDecimal
they can use the
compareTo
method.
Above is
W3Cschool编程狮
about
why Alibaba prohibits the use of BigDecimal's equals method for equivalent comparisons?
Related to the introduction, I hope to help you.