Double vs BigDecimal

1. Accurate floating-point operation:

In Java, sometimes accurate data is needed to ensure the accuracy of numerical values. You can find the problem by providing an example first:

public class FloatNumberTester {  
    public static void main(String args[]){  
        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);  
    }  
}  

According to our expectation, what should be the result above, but looking at the output, we will find the problem:

0.060000000000000005  
0.5800000000000001  
401.49999999999994  
1.2329999999999999  

In this case, the problem is relatively serious. If we use 123.3 yuan for transaction, but the computer refuses the transaction because of 1.2329999999999999, isn't it quite different from the actual situation.

2. Rounding:

Another calculation problem is rounding. However, Java computing itself cannot support rounding, such as:

public class GetThrowTester {  
    public static void main(String args[]){  
        System.out.println(4.015 * 100.0);  
    }  
}  

This output is:

401.49999999999994 

Therefore, it will be found that this situation does not guarantee rounding. If you want to round, there is only one way
java.text.DecimalFormat:

import java.text.DecimalFormat;  
public class NumberFormatMain {  
    public static void main(String args[]){  
        System.out.println(new DecimalFormat("0.00").format(4.025));  
        System.out.println(new DecimalFormat("0.00").format(4.024));  
    }  
}  

The above code output is:

4.02   
4.02   

Did you find a problem? Because decimal format uses the rounding mode, see the last part of this article for details of the rounding mode.  

3. Floating point output:

When the value of Java floating-point type is greater than 999999.0, it will be automatically converted into scientific counting method. See the following example:

public class FloatCounter {  
    public static void main(String args[]){  
        System.out.println(9969999999.04);  
        System.out.println(199999999.04);  
        System.out.println(1000000011.01);  
        System.out.println(9999999.04);  
    }  
}  

The output result is:

9.96999999904E9   
1.9999999904E8   
1.00000001101E9   
9999999.04  

But sometimes we don't need scientific counting method, but convert it into string, so it may be a little troublesome.  

Summary:

Therefore, in the project, for the operation of floating-point type and large integer, try not to use double, long and other basic data types and their wrapper classes, but use BigDecimal, BigInteger and other large value types provided in Java.  
However, here is a special explanation of the difference between the two constructors of BigDecimal class. They are:
new BigDecimal(String val) and new BigDecimal(double val)
Let's start with an example:

public class BigDecimalMain {  
    public static void main(String args[]){  
        System.out.println(new BigDecimal(123456789.01).toString());  
        System.out.println(new BigDecimal("123456789.01").toString());  
    }  
}  

The output result was unexpected once, and the difference between the two was clear at a glance:

123456789.01000000536441802978515625   
123456789.01   

Therefore, when you want to convert the original double type into BigDecimal type after relevant calculation, in order to prevent the deviation of precision, it is recommended to use this construction method with the parameter of String type. That is, new BigDecimal(String val).


BigDecimal rounding mode introduction:

Rounding mode in Java math. In roundingmode:
RoundingMode.CEILING: the rounding mode of rounding to positive infinity. If the result is positive, the rounding behavior is similar to roundingmode UP; If the result is negative, the rounding behavior is similar to roundingmode DOWN. Note that this rounding mode never reduces the calculated value

Enter numberUse the CEILING rounding mode to round numbers to one digit
5.5
2.5
1.1
1.0
-1.0-1 
-1.1-1 
-1.6-1 
-2.5-2
-5.5-5


RoundingMode.DOWN: the rounding mode of rounding to zero. Never add 1 (i.e. truncation) to the number in front of the discarded part. Note that this rounding mode never increases the absolute value of the calculated value

Enter numberUse the DOWN rounding mode to round a number to one digit
5.5
2.5
1.1
-1.0-1 
-1.6-1 
-2.5-2 
-5.5-5 


RoundingMode.FLOOR: the rounding mode of rounding to negative infinity. If the result is positive, the rounding behavior is similar to roundingmode DOWN; If the result is negative, the rounding behavior is similar to roundingmode UP. Note that this rounding mode never increases the calculated value

Enter numberUse the FLOOR rounding mode to round the input number to one digit
5.5
2.3
1.6
1.0
-1.1-2 
-2.5-3 
-5.5-6


RoundingMode.HALF_DOWN: the rounding mode of rounding in the direction closest to the number. If the distance from two adjacent numbers is equal, it will be rounded down. If the discarded part is > 0.5, the rounding behavior is the same as roundingmode UP; Otherwise, the rounding behavior is the same as roundingmode DOWN   

Enter numberUse half_ The down input mode is rounded to one bit
5.5
2.5
1.6
1.0
-1.1-1 
-1.6-2 
-2.5-2 
-5.5-5 


RoundingMode.HALF_EVEN: the rounding mode of rounding in the direction closest to the number. If the distance from two adjacent numbers is equal, it will be rounded to the adjacent even number. If the number on the left of the discarded part is odd, the rounding behavior is the same as roundingmode HALF_ UP; If it is an even number, the rounding behavior is the same as roundingmode HALF_ DOWN. Note that this rounding pattern statistically minimizes cumulative errors when repeating a series of calculations. This rounding model, also known as "banker rounding method", is mainly used in the United States. This rounding pattern is similar to the rounding strategy used in Java for float and double algorithms

Enter numberUse HALF_EVEN rounding mode rounds the input to one digit
5.5
2.5
1.6
1.1
-1.0-1 
-1.6-2 
-2.5-2 
-5.5-6 

RoundingMode.HALF_UP: the rounding mode of rounding in the direction closest to the number. If the distance from two adjacent numbers is equal, it will be rounded up. If the discarded part > = 0.5, the rounding behavior is the same as roundingmode UP; Otherwise, the rounding behavior is the same as roundingmode DOWN. Note that this rounding pattern is commonly referred to in schools as rounding

Enter numberUse HALF_UP rounding mode rounding to one digit
5.5
2.5
1.6
1.0
-1.1-1 
-1.6-2 
-2.5-3 
-5.5-6 


RoundingMode.UNNECESSARY: the rounding pattern used to assert that the requested operation has an exact result, so rounding is not required. If this rounding mode is specified for an operation that produces an exact result, an ArithmeticException is thrown

Enter numberUse UNNECESSARY mode
5.5Arimetexception thrown
2.5Throw ArithmeticException
1.6Throw ArithmeticException
1.0
-1.0-1.0 
-1.1Throw ArithmeticException
-1.6Throw ArithmeticException
-2.5Throw ArithmeticException
-5.5Throw ArithmeticException

RoundingMode.UP: rounding mode for rounding away from zero. Always add 1 to the number before the non-zero discards. Note that this rounding mode never reduces the absolute value of the calculated value

Enter numberUse the UP rounding mode to round the input number to one digit
5.5
1.6
1.1
1.0
-1.1-2 
-1.6-2 
-2.5-3 
-5.4-6


 

import  java.math.BigDecimal;   
import  java.text.DecimalFormat;   
/**  
 *Formatting using rounding mode
 **/   
public class   DoubleFormat {   
    public static void  main(String  args[]){   
        DoubleFormat format =  new  DoubleFormat();   
        System.out .println(format.doubleOutPut(12.345, 2));   
        System.out .println(format.roundNumber(12.335, 2));   
    }   
    public   String  doubleOutPut(double  v,Integer num){   
        if ( v == Double.valueOf(v).intValue()){   
            return  Double.valueOf(v).intValue() +  "" ;   
        }else {   
            BigDecimal b =  new  BigDecimal(Double.toString(v));   
            return  b.setScale(num,BigDecimal.ROUND_HALF_UP ).toString();   
        }   
    }   
    public   String  roundNumber(double  v,int  num){   
        String  fmtString =  "0000000000000000" ;  //16bit   
        fmtString = num>0 ?  "0."   + fmtString.substring(0,num):"0" ;   
        DecimalFormat dFormat =  new  DecimalFormat(fmtString);   
        return  dFormat.format(v);   
    }   
}

The output of this code is:

12.35   
12.34  

Reproduced in: Comparison between Double and BigDecimal - Rabbit bully summer - blog Garden

Keywords: Java source code

Added by n00854180t on Wed, 02 Mar 2022 11:10:19 +0200