double cannot be used as a money operation

Keywords: Programming Java

float and double can only be used for scientific calculation or engineering calculation. In business calculation, we need to use java.math.BigDecimal . I heard that a colleague said that a friend of his had been used by hackers because he used double to calculate money, resulting in a lot of losses. Let's talk about this.

brief introduction

The simple floating-point type float and double in Java can't be operated, or the precision of the operation will be lost, not only in Java, but also in many other programming languages. In most cases, the calculation results are accurate. Float and double can only be used for scientific calculation or engineering calculation. In business calculation, we need to use java.math.BigDecimal .

BigDecimal

BigDecimal has a variety of constructors, two of which are commonly used. One of them is not recommended, that is, double construction and String construction.

Tools

Since the construction method uses the construction method corresponding to String, if we want to do an addition operation, we need to first convert two floating-point numbers to String, and then make BigDecimal. Call the add method on one of them, pass in another as a parameter, and then convert the result of the operation (BigDecimal) to floating-point numbers. Can you stand such a cumbersome process? Next, we provide a tool class to simplify the operation.

import java.math.BigDecimal;
/**www.1b23.com
* Because Java's simple type can't accurately calculate floating-point numbers, this tool class provides precision
* True floating point arithmetic, including addition, subtraction, multiplication, division, and rounding.
*/
publicclass ArithUtil {
//Default division precision
privatestaticfinalint DEF_DIV_SCALE = 10;
/**www.1b23.com
* Provides accurate addition operations.
* @param v1 augend
* @param v2 Addend
* @return Sum of two parameters
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**www.1b23.com
* Provides accurate subtraction.
* @param v1 minuend
* @param v2 Subtraction
* @return Difference between two parameters
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**www.1b23.com
* Provides accurate multiplication.
* @param v1 Multiplier
* @param v2 multiplier
* @return Product of two parameters
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**www.1b23.com
* Provides (relatively) accurate division operations, accurate to
* 10 decimal places after the decimal point, and the number after the decimal point shall be rounded.
* @param v1 Divisor
* @param v2 Divisor
* @return Quotient of two parameters
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
/**www.1b23.com
* Provides (relatively) accurate division operations. In case of inexhaustible division, the scale parameter indicates
* Set the precision, and then round the numbers.
* @param v1 Divisor
* @param v2 Divisor
* @param scale Indicates that the representation needs to be accurate to several decimal places.
* @return Quotient of two parameters
*/
public static double div(double v1,double v2,int scale){
if(scale<0){
thrownew IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**www.1b23.com
* Provides accurate decimal rounding.
* @param v Number to be rounded
* @param scale How many decimal places to keep
* @return Rounded results
*/
public static double round(double v,int scale){
if(scale<0){
thrownew IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}

test

Posted by chrisredding on Tue, 19 May 2020 02:58:25 -0700