当前位置:网站首页>Step on the pit. The BigDecimal was improperly used, resulting in P0 accident!
Step on the pit. The BigDecimal was improperly used, resulting in P0 accident!
2022-06-10 18:11:00 【hello-java-maker】
Recommended today
Reduce try-catch , This is grace !
An addictive new generation of development artifacts , Say goodbye to Controller、Service、Dao Other methods
SpringBoot Realize face recognition function
believe me , Use Stream Can really make the code more elegant !
The most detailed thread pool in the whole network ThreadPoolExecutor Reading !
Batch splitting with multithreading List Import database , Efficiency bars !background
When we use the amount to calculate or display the amount, we often use BigDecimal, It is also a very recommended type when it comes to the amount .
BigDecimal It also provides many constructor methods , Improper use of these constructor methods may cause unnecessary trouble or even loss of money , Thus causing accident asset loss .
accident
Next, let's look at an accident at the cashier .
Problem description
The cashier reported an error in calculating the amount of goods , The order cannot be paid .
Accident level
P0
Accident process
as follows :
13:44, Get the alarm , Order payment failed , Payment availability reduced to 60%
13:50, Quickly roll back online code , Back to normal
14:20,review Code , Problems found in pre release verification
14:58, Modify the problem code to go online , Online recovery
The cause of the problem
BigDecimal Lost precision in amount calculation .
Cause analysis
First, let's use a piece of code to reproduce the root cause of the problem , As shown below :
public static void main(String[] args) {
BigDecimal bigDecimal=new BigDecimal(88);
System.out.println(bigDecimal);
bigDecimal=new BigDecimal("8.8");
System.out.println(bigDecimal);
bigDecimal=new BigDecimal(8.8);
System.out.println(bigDecimal);
}The results are as follows :

Found by test , When using double perhaps float These floating-point data types , Will lose precision ,String、int Will not be , Why is that ?
Let's open the constructor method to see the source code :
public static long doubleToLongBits(double value) {
long result = doubleToRawLongBits(value);
// Check for NaN based on values of bit fields, maximum
// exponent and nonzero significand.
if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
DoubleConsts.EXP_BIT_MASK) &&
(result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
result = 0x7ff8000000000000L;
return result;
} The problem is doubleToRawLongBits In this way , stay jdk in double class (float And int Corresponding ) Provided in double And long transformation ,doubleToRawLongBits Will be double Convert to long, This method is the original method ( The bottom is not java Realization , yes c++ Realized ).
double The reason why something goes wrong , It's because the decimal point to binary lost precision .

BigDecimal Expand decimal number in processing N Times make it count on integers , And keep the corresponding precision information .
①float and double type , It is mainly designed for scientific calculation and engineering calculation , The reason for performing binary floating-point operations , It is designed to provide accurate and fast approximate sum calculation over a wide range of numerical values .
② It doesn't provide completely accurate results , So it should not be used for precise results .
③ When the floating-point number reaches a certain large number , Will automatically use scientific counting , Such a representation is only approximate to the real number but not equal to the real number .
④ When decimals are converted to binary, there will be infinite cycles or the length of the floating-point mantissa will be exceeded .
summary
therefore , In the process of precision calculation , We try to use String Type to convert .
The correct usage is as follows :
BigDecimal bigDecimal2=new BigDecimal("8.8");
BigDecimal bigDecimal3=new BigDecimal("8.812");
System.out.println( bigDecimal2.compareTo(bigDecimal3));
System.out.println( bigDecimal2.add(bigDecimal3));BigDecimal What is created is an object , We can't use the traditional addition, subtraction, multiplication and division to calculate it , Must use his method , In our database store , If we use double perhaps float type , It needs to be calculated after round-trip conversion , Very inconvenient .
Tool sharing
So here we put together a util Class for everyone .
import java.math.BigDecimal;
/**
* @Author shuaige
* @Date 2022/4/17
* @Version 1.0
**/
public class BigDecimalUtils {
public static BigDecimal doubleAdd(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2);
}
public static BigDecimal floatAdd(float v1, float v2) {
BigDecimal b1 = new BigDecimal(Float.toString(v1));
BigDecimal b2 = new BigDecimal(Float.toString(v2));
return b1.add(b2);
}
public static BigDecimal doubleSub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2);
}
public static BigDecimal floatSub(float v1, float v2) {
BigDecimal b1 = new BigDecimal(Float.toString(v1));
BigDecimal b2 = new BigDecimal(Float.toString(v2));
return b1.subtract(b2);
}
public static BigDecimal doubleMul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2);
}
public static BigDecimal floatMul(float v1, float v2) {
BigDecimal b1 = new BigDecimal(Float.toString(v1));
BigDecimal b2 = new BigDecimal(Float.toString(v2));
return b1.multiply(b2);
}
public static BigDecimal doubleDiv(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
// Keep two decimal places ROUND_HALF_UP = rounding
return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal floatDiv(float v1, float v2) {
BigDecimal b1 = new BigDecimal(Float.toString(v1));
BigDecimal b2 = new BigDecimal(Float.toString(v2));
// Keep two decimal places ROUND_HALF_UP = rounding
return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);
}
/**
* Compare v1 v2 size
* @param v1
* @param v2
* @return v1>v2 return 1 v1=v2 return 0 v1<v2 return -1
*/
public static int doubleCompareTo(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.compareTo(b2);
}
public static int floatCompareTo(float v1, float v2) {
BigDecimal b1 = new BigDecimal(Float.toString(v1));
BigDecimal b2 = new BigDecimal(Float.toString(v2));
return b1.compareTo(b2);
}
}source :juejin.cn/post/7087404273503305736
Last , Recommend a planet of my knowledge , Join now , front 100 name , It only needs 25 element that will do , Very favorable .
边栏推荐
- js模糊阴影跟随动画js特效插件
- Noise line h5js effect realized by canvas
- pands pd. Detailed parsing of dataframe() function
- The short ticket hypothesis: finding sparse, trainable neural networks
- 【AXI】解读AXI协议双向握手机制的原理
- 信息学奥赛一本通 1280:【例9.24】滑雪 | OpenJudge NOI 2.6 90:滑雪 | 洛谷 P1434 [SHOI2002] 滑雪
- Abbexa丙烯酰胺-PEG-NHS说明书
- PCA principal component analysis tutorial (origin analysis & drawing, without R language)
- How will you integrate into the $20trillion "project economy" in five years
- LeetCode 255. 验证前序遍历序列二叉搜索树*
猜你喜欢

Wireshark learning notes (I) common function cases and skills

Container containing the most water

CDGA|工业企业进行数据治理的六个关键点

堆利用之chunk extend: HITCON tranining lab13

Mmdetection build_ Optimizer module interpretation

YML file configuration parameter definition dictionary and list

Numpy np set_ Usage of printoptions () -- control output mode

JS special effect of canvas divergent particle H5 animation

mmdetection之dataloader构建

如何定位游戏发热问题
随机推荐
The development of flutter in digital life and the landing practice of Tianyi cloud disk
LeetCode树经典题目(一)
LoRa模块无线收发通信技术详解
Numpy np set_ Usage of printoptions () -- control output mode
Jouer avec la classe de fonctions de pytorch
关于cmake和gcc的安装的记录
Abbexa低样本量鸡溶菌酶 C (LYZ) ELISA 试剂盒
高数_第6章无穷级数__正项级数的性质
基于业务沉淀组件 =&gt; manage-table
mmdetection之dataloader构建
MMdetection之build_optimizer模块解读
Some views on the current CIM (bim+gis) industry
玩轉Pytorch的Function類
IP总结(TCP/IP卷1和卷2)
AOE网关键路径
if else的使用太简单?(看懂这篇你的逻辑会进一步提升)
Summary of vim common commands
.NET 开源的免费午餐结束了?
Leetcode 321. Nombre maximum de raccords
搭建在线帮助中心,轻松帮助客户解决问题