这篇文章主要介绍了Java中BigDecimal,DateFormatter 和迭代器的陷阱,文章围绕主题展开详细的内容介绍,感兴趣的小伙伴可以参考一下
前言:
使用 IDEA 创建一个 Maven 项目 calculate-date-traps 并导入 Junit 依赖。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
在进行计费时使用 Double 和 Float 类型计算经常会出现丢失精度的情况,在 test 包下新建一个测试类 ScaleLostTest。
public class ScaleLostTest {
@Test
public void testDoubleLostScale(){
double alpha = 1;
double bravo = 20.2;
double charlie = 400.03;
System.out.println(alpha + bravo + charlie);
}
}
执行上述代码,输出结果如下 :
使用 Double 类型进行精确运算出现了精度问题。
代码中所使用的这些数最终都会转换成二进制,而浮点类型的数转换成二进制并不是精确地二进制,只能是最接近的二进制,这是应为浮点数是由指数和尾数两部分组成,所以在浮点数计算的过程中会出现丢失精度的问题。
如果恰巧计算结果的二进制能和十进制准确转换那么自然也就不会出现丢失精度的问题了。浮点数并不适合进行精确计算而更适合科学计算。而 BigDecimal 类型的核心就是精度,在 test 包下新建一个测试类 BigDecimalTest
public class BigDecimalTest {
@Test
public void testScaleException(){
BigDecimal bigDecimal = new BigDecimal("12138.121");
BigDecimal res = bigDecimal.setScale(2);
System.out.println(res);
}
}
执行上述代码,输出结果如下:
设置的精度既小数点的位数比原来小会报错。设置为5,会自动补上0,再次执行测试输出结果如下:
只想保留两位数字,如何解决?如何对原始数字进行舍入?BigDecimal支持的舍入方式有很多中,向上取整,向下取整,四舍五入等
@Test
public void testChangeScale(){
BigDecimal bigDecimal = new BigDecimal("12138.121");
BigDecimal res = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(res);
}
12138.128
测试其他舍入方式,除法运算,除不尽出现异常问题,除不尽,既无限循环的问题
@Test
public void testDivideException(){
BigDecimal d1 = new BigDecimal(10);
BigDecimal d2 = new BigDecimal(3);
System.out.println(d1.divide(d2));
}
@Test
public void testSolveDivideException(){
BigDecimal d1 = new BigDecimal(10);
BigDecimal d2 = new BigDecimal(3);
System.out.println(d1.divide(d2, 2, BigDecimal.ROUND_HALF_UP));
}
指定精度和舍入方式
总结:使用BigDecimal一定要指定保留小数点的位数和指定的舍入方式
精度问题导致结果比较不一致:
@Test
public void testCompare(){
BigDecimal d1 = new BigDecimal("0");
BigDecimal d2 = new BigDecimal("0.0");
System.out.println(d1.equals(d2));
System.out.println(d1.compareTo(d2));
}
equals()方法,精度不同直接返回false
到此这篇关于Java中BigDecimal,DateFormatter 和迭代器的"陷阱"的文章就介绍到这了,更多相关java 迭代器陷阱内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
本文标题为:Java中BigDecimal,DateFormatter 和迭代器的"陷阱"
基础教程推荐
- java实现多人聊天系统 2023-05-19
- Java数据结构之对象比较详解 2023-03-07
- Java实现查找文件和替换文件内容 2023-04-06
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- Java实现线程插队的示例代码 2022-09-03
- springboot自定义starter方法及注解实例 2023-03-31
- java基础知识之FileInputStream流的使用 2023-08-11
- Java文件管理操作的知识点整理 2023-05-19
- Java并发编程进阶之线程控制篇 2023-03-07