7
7
8
8
《阿里巴巴 Java 开发手册》中提到:“为了避免精度丢失,可以使用 ` BigDecimal ` 来进行浮点数的运算”。
9
9
10
- 这篇文章,我就简单解释一下浮点数运算出现精度丢失的原因以及 ` BigDecimal ` 的常见用法,希望对大家有帮助!
11
-
12
- ## BigDecimal 介绍
13
-
14
- ` BigDecimal ` 可以实现对浮点数的运算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 ` BigDecimal ` 来做的。
15
-
16
- 纳尼,浮点数的运算竟然还会有精度丢失的风险吗?确实会!
10
+ 浮点数的运算竟然还会有精度丢失的风险吗?确实会!
17
11
18
12
示例代码:
19
13
@@ -44,25 +38,19 @@ System.out.println(a == b);// false
44
38
45
39
关于浮点数的更多内容,建议看一下[ 计算机系统基础(四)浮点数] ( http://kaito-kidd.com/2018/08/08/computer-system-float-point/ ) 这篇文章。
46
40
47
- ## BigDecimal 的用处
41
+ ## BigDecimal 介绍
48
42
49
- 《阿里巴巴 Java 开发手册》中提到: ** 浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。 **
43
+ ` BigDecimal ` 可以实现对浮点数的运算,不会造成精度丢失。
50
44
51
- ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/image-20211213101646884.png )
45
+ 通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 ` BigDecimal ` 来做的。
52
46
53
- 具体原因我们在上面已经详细介绍了,这里就不多提了,我们下面直接上实例:
47
+ 《阿里巴巴 Java 开发手册》中提到: ** 浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能用 equals 来判断。 **
54
48
55
- ``` java
56
- float a = 1.0f - 0.9f ;
57
- float b = 0.9f - 0.8f ;
58
- System . out. println(a);// 0.100000024
59
- System . out. println(b);// 0.099999964
60
- System . out. println(a == b);// false
61
- ```
49
+ ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/image-20211213101646884.png )
62
50
63
- 从输出结果就可以看出发生精度丢失的问题 。
51
+ 具体原因我们在上面已经详细介绍了,这里就不多提了 。
64
52
65
- 想要解决这个问题也很简单,直接使用 ` BigDecimal ` 来定义浮点数的值,再进行浮点数的运算操作即可 。
53
+ 想要解决浮点数运算精度丢失这个问题,可以直接使用 ` BigDecimal ` 来定义浮点数的值,然后再进行浮点数的运算操作即可 。
66
54
67
55
``` java
68
56
BigDecimal a = new BigDecimal (" 1.0" );
@@ -72,13 +60,19 @@ BigDecimal c = new BigDecimal("0.8");
72
60
BigDecimal x = a. subtract(b);
73
61
BigDecimal y = b. subtract(c);
74
62
75
- System . out. println(x); /* 0.1 */
76
- System . out. println(y); /* 0.1 */
77
- System . out. println(Objects . equals(x, y)); /* true */
63
+ System . out. println(x. compareTo(y));// 0
78
64
```
79
65
80
66
## BigDecimal 常见方法
81
67
68
+ ### 创建
69
+
70
+ 我们在使用 ` BigDecimal ` 时,为了防止精度丢失,推荐使用它的` BigDecimal(String val) ` 构造方法或者 ` BigDecimal.valueOf(double val) ` 静态方法来创建对象。
71
+
72
+ 《阿里巴巴 Java 开发手册》对这部分内容也有提到,如下图所示。
73
+
74
+ ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/image-20211213102222601.png )
75
+
82
76
### 加减乘除
83
77
84
78
` add ` 方法用于将两个 ` BigDecimal ` 对象相加,` subtract ` 方法用于将两个 ` BigDecimal ` 对象相减。` multiply ` 方法用于将两个 ` BigDecimal ` 对象相乘,` divide ` 方法用于将两个 ` BigDecimal ` 对象相除。
@@ -144,13 +138,33 @@ BigDecimal n = m.setScale(3,RoundingMode.HALF_DOWN);
144
138
System . out. println(n);// 1.255
145
139
```
146
140
147
- ## BigDecimal 的使用注意事项
141
+ ## BigDecimal 等值比较问题
148
142
149
- 注意:我们在使用 ` BigDecimal ` 时,为了防止精度丢失,推荐使用它的 ` BigDecimal(String val) ` 构造方法或者 ` BigDecimal.valueOf(double val) ` 静态方法来创建对象。
143
+ 《阿里巴巴 Java 开发手册》中提到:
150
144
151
- 《阿里巴巴 Java 开发手册》对这部分内容也有提到,如下图所示。
145
+ ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/java/basis/image-20220714161315993.png )
152
146
153
- ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/image-20211213102222601.png )
147
+ ` BigDecimal ` 使用 ` equals() ` 方法进行等值比较出现问题的代码示例:
148
+
149
+ ``` java
150
+ BigDecimal a = new BigDecimal (" 1" );
151
+ BigDecimal b = new BigDecimal (" 1.0" );
152
+ System . out. println(a. equals(b));// false
153
+ ```
154
+
155
+ 这是因为 ` equals() ` 方法不仅仅会比较值的大小(value)还会比较精度(scale),而 ` compareTo() ` 方法比较的时候会忽略精度。
156
+
157
+ 1.0 的 scale 是 1,1 的 scale 是 0,因此 ` a.equals(b) ` 的结果是 false。
158
+
159
+ ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/java/basis/image-20220714164706390.png )
160
+
161
+ ` compareTo() ` 方法可以比较两个 ` BigDecimal ` 的值,如果相等就返回 0,如果第 1 个数比第 2 个数大则返回 1,反之返回-1。
162
+
163
+ ``` java
164
+ BigDecimal a = new BigDecimal (" 1" );
165
+ BigDecimal b = new BigDecimal (" 1.0" );
166
+ System . out. println(a. compareTo(b));// 0
167
+ ```
154
168
155
169
## BigDecimal 工具类分享
156
170
@@ -342,4 +356,3 @@ public class BigDecimalUtil {
342
356
浮点数没有办法用二进制精确表示,因此存在精度丢失的风险。
343
357
344
358
不过,Java 提供了` BigDecimal ` 来操作浮点数。` BigDecimal ` 的实现利用到了 ` BigInteger ` (用来操作大整数), 所不同的是 ` BigDecimal ` 加入了小数位的概念。
345
-
0 commit comments