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.


  1. BigDecimalClass definition:
   BigDecimal bd = new BigDecimal("123.456");
Copy the code
  1. BigDecimalusescale()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
  1. BigDecimalIn thestripTrailingZeros()Method, can beBigDecimalAn 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.

  1. BigDecimalYou 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
  1. BigDecimalAddition, 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
  1. BigDecimalWhen 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
  1. Can beBigDecimalDivide 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
  1. calldivideAndRemainder()Method, the returned array contains twoBigDecimalThe 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 twoBigDecimalIs 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
  1. Compare the twoBigDecimalWhen the values of are equal, note that useequals()The method requires not only twoBigDecimalThe 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()

  1. usecompareTo()Method to compare the size of two numbers, which returns -1, 1, and 1, respectively, based on the size of each value0Is 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
  1. To viewBigDecimalThe source code can be found oneBigDecimalIs through aBigIntegerAnd ascaleIs represented by, i.eBigIntegerRepresents a complete integer, andscaleRepresents 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: