当前位置:网站首页>Is BigDecimal safe to calculate the amount? Look at these five pits~~
Is BigDecimal safe to calculate the amount? Look at these five pits~~
2022-07-04 14:48:00 【Hollis Chuang】
See an article because it is not used in the amount calculation BigDecimal
And the article that caused the failure , But unless in some very simple scenes , Settlement of remittance businesses will not be directly used BigDecimal
To calculate the amount , For two reasons :
BigDecimal
There are still many hidden pitsBigDecimal
The unit that did not provide the amount
1. BigDecimal
Five easy pits in
1.1 new BigDecimal()
still BigDecimal#valueOf()
?
First look at the following code
BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = BigDecimal.valueOf(0.01);
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);
The output to the console is :
bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01
The reason for this difference is 0.1 This digital computer cannot accurately express , Send BigDecimal
The accuracy has been lost by , and BigDecimal#valueOf
The implementation of is completely different
public static BigDecimal valueOf(double val) {
// Reminder: a zero double returns '0.0', so we cannot fastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
return new BigDecimal(Double.toString(val));
}
It uses the corresponding string of floating-point numbers to construct BigDecimal
object , Therefore, the accuracy problem is avoided . So we should try to use strings instead of floating-point numbers to construct BigDecimal
object , If it doesn't work , Just use BigDecimal#valueOf()
Methods! .
1.2 Equivalence comparison
BigDecimal bd1 = new BigDecimal("1.0");
BigDecimal bd2 = new BigDecimal("1.00");
System.out.println(bd1.equals(bd2));
System.out.println(bd1.compareTo(bd2));
The output of the console will be :
false
0
The reason is ,BigDecimal
in equals
The implementation of the method will compare the accuracy of two numbers , and compareTo
Method will only compare the size of the value .
1.3 BigDecimal
Does not mean infinite accuracy
First look at this code
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("3.0");
a.divide(b) // results in the following exception.
The result is an exception :
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
About this exception ,Oracle The official documents of have specific instructions
If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations.
The main idea is , If the result of the quotient of division is an infinite decimal, but we expect to return the exact result , Then the program will throw an exception . Back to our example , We need to tell JVM
We don't need to return exact results
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("3.0");
a.divide(b, 2, RoundingMode.HALF_UP)// 0.33
1.4 BigDecimal
Turn it back String
Be careful
BigDecimal d = BigDecimal.valueOf(12334535345456700.12345634534534578901);
String out = d.toString(); // Or perform any formatting that needs to be done
System.out.println(out); // 1.23345353454567E+16
It can be seen that the results have been converted into scientific counting , Maybe this is not the expected result BigDecimal
There are three methods that can be converted to the corresponding string type , Remember not to use the wrong :
String toString(); // Use scientific counting when necessary
String toPlainString(); // No scientific counting
String toEngineeringString(); // The method of recording numbers often used in engineering calculation , Similar to scientific counting , But ask for 10 The power of must be 3 Multiple
1.5 The execution sequence cannot be changed ( The commutative law of multiplication fails )
It is common sense that multiplication satisfies the commutative law , But in the world of computers , There will be situations that do not satisfy the commutative law of multiplication
BigDecimal a = BigDecimal.valueOf(1.0);
BigDecimal b = BigDecimal.valueOf(3.0);
BigDecimal c = BigDecimal.valueOf(3.0);
System.out.println(a.divide(b, 2, RoundingMode.HALF_UP).multiply(c)); // 0.990
System.out.println(a.multiply(c).divide(b, 2, RoundingMode.HALF_UP)); // 1.00
Don't underestimate this 0.01 The difference between , In Huijin , There will be a very large amount difference .
2. Best practices
About the amount calculation , Many business teams will be based on BigDecimal
One more Money
class , In fact, we can directly use a semi official Money
class :JSR 354 , Although not in Java 9
To become Java
standard , It is likely to be integrated into subsequent Java
Become the official library in version .
2.1 maven
coordinate
<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>1.1</version>
</dependency>
2.2 newly build Money
class
CurrencyUnit cny = Monetary.getCurrency("CNY");
Money money = Money.of(1.0, cny);
// perhaps Money money = Money.of(1.0, "CNY");
//System.out.println(money);
2.3 Amount calculation
CurrencyUnit cny = Monetary.getCurrency("CNY");
Money oneYuan = Money.of(1.0, cny);
Money threeYuan = oneYuan.add(Money.of(2.0, "CNY")); //CNY 3
Money tenYuan = oneYuan.multiply(10); // CNY 10
Money fiveFen = oneYuan.divide(2); //CNY 0.5
2.4 More equal
Money fiveFen = Money.of(0.5, "CNY"); //CNY 0.5
Money anotherFiveFen = Money.of(0.50, "CNY"); // CNY 0.50
System.out.println(fiveFen.equals(anotherFiveFen)); // true
You can see , This class abstracts the amount explicitly , Increase the unit of the amount , It also avoids direct use BigDecimal
Some pits .
End
My new book 《 In depth understanding of Java The core technology 》 It's on the market , After listing, it has been ranked in Jingdong best seller list for several times , At present 6 In the discount , If you want to start, don't miss it ~ Long press the QR code to buy ~
Long press to scan code and enjoy 6 A discount
Previous recommendation
B The station was scolded on the hot search ..
There is Tao without skill , It can be done with skill ; No way with skill , Stop at surgery
Welcome to pay attention Java Road official account
Good article , I was watching ️
边栏推荐
- C language small commodity management system
- Chapter 16 string localization and message Dictionary (2)
- C language course design questions
- PyTorch的自动求导机制详细解析,PyTorch的核心魔法
- remount of the / superblock failed: Permission denied
- LVGL 8.2 LED
- [algorithm leetcode] interview question 04.03 Specific depth node linked list (Multilingual Implementation)
- C language book rental management system
- LVGL 8.2 List
- Wt588f02b-8s (c006_03) single chip voice IC scheme enables smart doorbell design to reduce cost and increase efficiency
猜你喜欢
Wt588f02b-8s (c006_03) single chip voice IC scheme enables smart doorbell design to reduce cost and increase efficiency
数据湖(十三):Spark与Iceberg整合DDL操作
Count the running time of PHP program and set the maximum running time of PHP
Detailed explanation of visual studio debugging methods
Combined with case: the usage of the lowest API (processfunction) in Flink framework
Ali was laid off employees, looking for a job n day, headhunters came bad news
leetcode:6110. 网格图中递增路径的数目【dfs + cache】
LVGL 8.2 Line wrap, recoloring and scrolling
92. (cesium chapter) cesium building layering
Practical puzzle solving | how to extract irregular ROI regions in opencv
随机推荐
Real time data warehouse
关于FPGA底层资源的细节问题
内存管理总结
Why do domestic mobile phone users choose iPhone when changing a mobile phone?
Test evaluation of software testing
LVLG 8.2 circular scrolling animation of a label
An overview of 2D human posture estimation
LVGL 8.2 text shadow
开发中常见问题总结
Sqlserver functions, creation and use of stored procedures
Leetcode 1200 minimum absolute difference [sort] the way of leetcode in heroding
openresty 限流
实战解惑 | OpenCV中如何提取不规则ROI区域
Respect others' behavior
LVLG 8.2 circular scrolling animation of a label
leecode学习笔记-约瑟夫问题
【MySQL从入门到精通】【高级篇】(四)MySQL权限管理与控制
Data center concept
IO flow: node flow and processing flow are summarized in detail.
ES6 modularization