当前位置:网站首页>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 17:33:00 【Young】
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 .
边栏推荐
- 2022年国内云管平台厂商哪家好?为什么?
- It's too convenient. You can complete the code release and approval by nailing it!
- Go micro tutorial - Chapter 2 go micro V3 using gin and etcd
- 一加10 Pro和iPhone 13怎么选?
- Pytorch深度学习之环境搭建
- Oppo Xiaobu launched Obert, a large pre training model, and promoted to the top of kgclue
- Blood spitting finishing nanny level series tutorial - play Fiddler bag grabbing tutorial (2) - first meet fiddler, let you have a rational understanding
- R语言plotly可视化:plotly可视化多分类变量小提琴图(multiple variable violin plot in R with plotly)
- To sort out messy header files, I use include what you use
- 《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(2)-初识Fiddler让你理性认识一下
猜你喜欢
La 18e Conférence internationale de l'IET sur le transport d'électricité en courant alternatif et en courant continu (acdc2022) s'est tenue avec succès en ligne.
Solution of dealer collaboration system in building materials industry: empowering enterprises to build core competitiveness
【Go ~ 0到1 】 第六天 文件的读写与创建
Analysis of abnormal frequency of minor GC in container environment
Oppo Xiaobu launched Obert, a large pre training model, and promoted to the top of kgclue
【云原生】服务网格是什么“格”?
居家打工年入800多万,一共五份全职工作,他还有时间打游戏
【HCIA持续更新】WLAN工作流程概述
VSCode修改缩进不成功,一保存就缩进四个空格
51 single chip microcomputer temperature alarm based on WiFi control
随机推荐
Solution of commercial supply chain coordination system in the mineral industry: build a digital intelligent supply chain platform to ensure the safe supply of mineral resources
kaili不能输入中文怎么办???
New technology releases a small program UNIPRO to meet customers' mobile office scenarios
Kunming Third Ring Road Closure project will pass through these places. Is there one near your home?
Great Wall Securities security does not open a securities account
2022PMP考试基本情况详情了解
S2b2b solution for lighting industry: efficiently enable the industrial supply chain and improve the economic benefits of enterprises
Ble HCI flow control mechanism
Linear time sequencing
Pytorch深度学习之环境搭建
雨量预警广播自动化数据平台BWII 型广播预警监测仪
The company needs to be monitored. How do ZABBIX and Prometheus choose? That's the right choice!
[acwing] 58 weeks 4490 dyeing
[Acwing] 58周赛 4489. 最长子序列
curl 命令妙用
Go micro tutorial - Chapter 2 go micro V3 using gin and etcd
设置窗体透明 隐藏任务栏 与全屏显示
leetcode:421. The maximum XOR value of two numbers in the array
leetcode:421. 数组中两个数的最大异或值
R language plot visualization: plot visualizes overlapping histograms and uses geom at the top edge of the histogram_ The rug function adds marginal rug plots