Basic data types
Floating point numbers have errors
Floating-point numbers have some errors. For example:
public class Demo {
public static void main(String[] args) {
System.out.println(0.1+0.2= =0.3);/ / output is false}}Copy the code
The output value of this code is false because floating-point numbers are error-prone. Yi means 0.1 is not exactly 0.1 when stored on the computer. It could be 0.1000000001 or some other number, and 0.2 or 0.3 is the same. So 0.1+0.2 and 0.3 are not equal in computers.
Because floating point numbers have this property, we try to avoid floating point comparisons in our programming.
If you must use floating-point comparisons, you can use the following method:
public class Demo {
public static void main(String[] args) {
float n = (float)1e-6;// represents 10 to the -6
System.out.println(0.1+0.2 - 0.3 < n);/ / output true}}Copy the code
Output value of the code above is true, the principle of this method is that if the two Numbers are small enough, small enough to ignore the words don’t remember, and 6 of the limits set here is 10 square, it proved that comparing the two can be thought of as equal, this method can only be said in the floating point number of digits after the decimal point is not the time for a lot of use.
Let’s look at an extreme case where the code looks like this:
public class Demo {
public static void main(String[] args) {
System.out.println(0.30000000000000001= =0.3);/ / output true}}Copy the code
The above code prints true, but in fact we can see visually that the two numbers are very close, but they are definitely not equal, such extreme numbers we can not use the above method to compare, so remember this sentence: try to avoid floating point comparison.
BigDecimal class
Now that we know floating point numbers are error-prone, we definitely don’t use floats and doubles when the data itself needs to be stored accurately, such as money amounts. In this case we typically use the BigDecimal class, which is a class that can store exact floating-point numbers.
BigDecimal
Class definition:
BigDecimal bd = new BigDecimal("123.456");
Copy the code
BigDecimal
usescale()
Represents decimal places, for example:
BigDecimal d1 = new BigDecimal("987.65");
BigDecimal d2 = new BigDecimal("987.6500");
BigDecimal d3 = new BigDecimal("98765400");
System.out.println(d1.scale()); // 2, representing two decimal places
System.out.println(d2.scale()); / / 4
System.out.println(d3.scale()); / / 0
Copy the code
BigDecimal
In thestripTrailingZeros()
Method, can beBigDecimal
An equal number formatted to remove the trailing 0:
BigDecimal d1 = new BigDecimal("123.4500");
BigDecimal d2 = d1.stripTrailingZeros();
System.out.println(d1+""+d1.scale()); // 123.4500 4
System.out.println(d2+""+d2.scale()); // 123.45 2, because 00 is removed
BigDecimal d3 = new BigDecimal("1234500");
BigDecimal d4 = d3.stripTrailingZeros();
System.out.println(d3+""+d3.scale()); / / 1234500
System.out.println(d4+""+d4.scale()); // 1.2345E+6 -2
Copy the code
BigDecimal’s scale() returns a negative number, for example, -2, indicating that the number is an integer with two trailing zeros. So that’s what happened with d4 above, when you get rid of the 0’s, it doesn’t change, it just changes the notation.
BigDecimal
You can set itscale
, if the accuracy is lower than the original value, then round or truncate as specified:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Demo {
public static void main(String[] args) {
BigDecimal d1 = new BigDecimal("123.456789");
BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // Round to 123.4568
BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // Direct truncation, 123.4567
System.out.println(d2);/ / 123.4568
System.out.println(d3);/ / 123.4567}}Copy the code
BigDecimal
Addition, subtraction, multiplication, and division of:
import java.math.BigDecimal;
public class Demo {
public static void main(String[] args) {
BigDecimal d1 = new BigDecimal("124.44");
BigDecimal d2 = new BigDecimal("12.2");
System.out.println(d1.add(d2));/ / d1 + 136.64 d2
System.out.println(d1.subtract(d2));/ / d1, d2 112.24
System.out.println(d1.multiply(d2));/ / d1, d2 1518.168
System.out.println(d1.divide(d2));/ / d1 / d2 is 10.2}}Copy the code
BigDecimal
When doing addition, subtraction, and multiplication, the precision will not be lost, but when doing division, there is a case that cannot be divided, then we must specify the precision and how to truncate:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Demo {
public static void main(String[] args) {
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("23.456789");
BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // Keep 10 decimal places and round them
BigDecimal d4 = d1.divide(d2); // Error: ArithmeticException, because it is ArithmeticException}}Copy the code
- Can be
BigDecimal
Divide and find the rest:
import java.math.BigDecimal;
public class Demo {
public static void main(String[] args) {
BigDecimal n = new BigDecimal("22.444");
BigDecimal m = new BigDecimal("0.23");
BigDecimal[] dr = n.divideAndRemainder(m);
System.out.println(dr[0]); / / 97.0
System.out.println(dr[1]); / / 0.134}}Copy the code
- call
divideAndRemainder()
Method, the returned array contains twoBigDecimal
The first is the quotient, the second is the remainder, the quotient is always an integer, the remainder is never greater than the remainder, we can use this method to determine twoBigDecimal
Is it an integer multiple?
BigDecimal n = new BigDecimal("12.34");
BigDecimal m = new BigDecimal("0.12");
BigDecimal[] dr = n.divideAndRemainder(m);
if (dr[1].signum() == 0) {// Signum () returns three values based on this BigDecimal -1, 1, and 0 for numbers less than 0, greater than 0, and equal to 0, respectively
// n is a multiple of m
}
Copy the code
- Compare the two
BigDecimal
When the values of are equal, note that useequals()
The method requires not only twoBigDecimal
The values of alpha and beta are equal to each otherscale()
Is equal to:
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.45000");
System.out.println(d1.equals(d2)); // false, because scale is different
System.out.println(d1.equals(d2.stripTrailingZeros())); // true, because d2 removes the tail 0 and scale becomes 2, the same as d1
Copy the code
Note: Compare two BigDecimal values using compareTo(), not equals()
- use
compareTo()
Method to compare the size of two numbers, which returns -1, 1, and 1, respectively, based on the size of each value0
Is less than, greater than, and equal to respectively.
import java.math.BigDecimal;
public class Demo {
public static void main(String[] args) {
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.45000");
BigDecimal d3 = new BigDecimal("123.40");
System.out.println(d1.compareTo(d2)); / / 0
System.out.println(d1.compareTo(d3));// 1
System.out.println(d3.compareTo(d2));// -1}}Copy the code
- To view
BigDecimal
The source code can be found oneBigDecimal
Is through aBigInteger
And ascale
Is represented by, i.eBigInteger
Represents a complete integer, andscale
Represents the number of decimal places:
public class BigDecimal extends Number implements Comparable<BigDecimal> {
private final BigInteger intVal;
private final int scale;
}
Copy the code
For more exciting content, please pay attention to wechat public number: