首页 > 编程语言 >解决java中0.1+0.2=0.30000000000000004的问题

解决java中0.1+0.2=0.30000000000000004的问题

时间:2023-11-13 20:12:12浏览次数:41  
标签:java BigDecimal val 0.1 double 0.2 对象

 前言

在现实中我们都知道:

0.1+0.2=0.3

但是在程序中会出现这样的结果:

0.1+0.2=0.30000000000000004

原因

对于0.1来说,其本质是 1 / 10,那么若你用二进制表示它们,然后除的话,是这样的:1 / 1010,然而这一个是除不尽的,是无穷循环。

 ===> 0.0 00110011001100110011001100110011... 其中0011循环

而0.2表示为0.0011001100110011...

而在二进制中 1 + 1 = 10,所以 0.1 + 0.2 = 0.0100110011001100...

转成10进制就近似表示为 0.30000000000000004

结论

这是由于计算机采用二进制存储浮点数,而二进制无法准确地表示十进制小数0.1和0.2,会发生精度误差。在计算0.1+0.2时,计算机实际上是计算这两个数的近似值的和,因此得到的结果也是一个近似值,其末尾的小数位可能会有误差。

解决方法

使用Java中的BigDecimal类。

Java中的基本数据类型(如double和float)是有限的,因此它们对于小数计算可能会产生误差。在需要高精度计算时,可以使用Java中的BigDecimal类。

BigDecimal类可以处理大量的小数位数,避免了在浮点数位数过多时出现的不精确问题。以下情况可能需要使用BigDecimal类:

  1. 当需要精确计算小数,需要避免由于精度丢失而导致错误结果时;
  2. 当需要进行货币计算时,例如金融应用程序;
  3. 当需要进行科学计算时,需要高精度的数据存储。

BigDecimal 常用的构造方法如下。

BigDecimal(String val)用一个字符串值创建一个BigDecimal对象。
BigDecimal(double val)用一个double值创建一个BigDecimal对象。
BigDecimal(long val)用一个long值创建一个BigDecimal对象。
BigDecimal(BigInteger val)用一个BigInteger值创建一个BigDecimal对象。

参数类型为double的构造方法的结果有一定的不可预知性,因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。

而参数类型为String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言, 通常建议优先使用String构造方法。

下面列出了 BigDecimal 类用于实现加、减、乘和除运算的方法。

add(BigDecimal val)将当前BigDecimal对象与另一个BigDecimal对象相加。
subtract(BigDecimal val)将当前BigDecimal对象与另一个BigDecimal对象相减。
multiply(BigDecimal val)将当前BigDecimal对象与另一个BigDecimal对象相乘。
divide(BigDecimal val)将当前BigDecimal对象与另一个BigDecimal对象相除。

除此之外BigDecimal 类的其他方法。

compareTo(BigDecimal val)比较当前BigDecimal对象与另一个BigDecimal对象的大小。
negate()将当前BigDecimal对象取相反数。
abs()将当前BigDecimal对象取绝对值。
round(MathContext mc)将当前BigDecimal对象按照指定的精度进行四舍五入。
intValue()将当前BigDecimal对象转换为int类型。
doubleValue()将当前BigDecimal对象转换为double类型。
toString()将当前BigDecimal对象转换为字符串。

测试代码: 

  1. public class Main {
  2. public static void main(String[] args) {
  3. BigDecimal a = new BigDecimal("0.1");
  4. BigDecimal b = new BigDecimal("0.2");
  5. BigDecimal c = a.add(b);
  6. System.out.println(c);
  7. }
  8. }

 运行结果:

 总结

1、在需要精确的小数计算时再使用BigDecimal,BigDecimal的性能比double和float差,在处理庞大,复杂的运算时尤为明显。故一般精度的计算没必要使用BigDecimal。
2、尽量使用参数类型为String的构造函数。
3、BigDecimal都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。

标签:java,BigDecimal,val,0.1,double,0.2,对象
From: https://www.cnblogs.com/echosada/p/17830049.html

相关文章

  • 20 个好用的一行 Java代码
    今天分享给大家20个令人惊叹的Java一行代码,让你们的工作更轻松。一起来看看吧!1.获取浏览器Cookie的值使用document.cookie来获取Cookie的值。2.将RGB转换为十六进制3.复制到剪贴板使用navigator.clipboard.writeText轻松将任何文本复制到剪贴板上。4.检查日期是否......
  • JavaSE DataStructure
    JavaSEDataStructureListArrayListArrayListDemo1点击查看代码importjava.util.ArrayList;importjava.util.Collection;importjava.util.Iterator;classArrayListDemo1{publicstaticvoidmain(String[]args){Collection<String>list=newA......
  • Java文件处理(一):创建文件、遍历文件夹、删除文件/文件夹
    本篇以代码为核心,在实践中自学吧年轻人~非常好迭代作业,爱来自BUAAFile对象要进行文件处理肯定需要File类啦。File的实例是一个实例(?),但是可以链接到本地的文件、文件夹,并对它们进行操作。从下面的一些示例中可以看到,同一份本地文件可以拥有多个File对象;同时,构造一个File对象......
  • macOs Catalina 10.15.7安装xcode
    iMac新装了系统(Catalina10.15.7)之后,安装git提示缺少xcode试了以下方法,都没有成功:1、执行 xcode-select--install,提示:requestedforcommandlinedevelopertools2、通过appstore下载xcode,提示:不能将Xcode安装在macOs上,因为需要macOsv13.5或更高版本 查询了网上的方法......
  • java里junit 单元测试、注释(入门)
    什么是Junit单元测试?JUnit单元测试是指使用JUnit框架编写的针对代码中小的、独立的模块(通常是方法或者类)的测试。在JUnit中,您可以使用断言来验证代码的行为是否符合预期,以及使用注解来标记测试方法、测试套件等。执行单元测试可以帮助验证代码是否满足特定的业务需求和技术......
  • java中一些空判断|ObjectUtils
    为什么用ObjectUtils?在java中判断对象是否为null,常常不止判断对象是否为null,如果对象是集合,数组,字符串等等特殊类型,还需要检查是否为空(元素个数为0或者长度为0)ObjectUtils.isEmpty可以简化下面这些问题(当然,你使用的是spring)对象为null。对象是数组,且长度为0。对象是集合(Coll......
  • java基础学习:强制类型转换
    1.2.   代码:packagecom.itheima.type;publicclassType3{publicstaticvoidmain(String[]args){//掌握强制类型转换inta=20;//byteb=a;报错,直接将类型范围大的变量转换为类型范围小的byteb=(byte)a;//alt+e......
  • 中国银行模拟器app,用java设计框架,图片网上找的,提供代码,仅供娱乐
    回执单生成器的Java程序需要涉及到一些基本的Java编程技能,包括创建类、处理用户输入和格式化输出。下面是一个简单的示例代码,用于生成一个简易的回执单。这个程序将接收用户的输入,然后生成一个格式化的回执单。请注意,这个示例是基础的,并没有实现完整的错误处理或复杂的用户界面。......
  • 秦疆的Java课程笔记:27 基础 基本运算符
    Java语言支持的运算符:算数运算符:基础四则运算:+加法,-减法,*乘法,/除法%取余,或称“模运算”++自增,--自减赋值运算符:=关系运算符:>大于,<小于,>=大于等于,<=小于等于==等于,!=不等于instanceof对象运算符,用来判断一个对象是否属于某个指定的类或其子类的实例,如果是,返回true,否则......
  • java异常处理机制(三)之常见的异常
    1.算术异常算术异常(ArithmeticException)算术异常:被除数为0是就会产生异常 运行结果: 2.数组越界异常数组越界(ArrayIndexOutOfBoundsException)数组越界异常:当数组长度没有用户使用数组的长度长时就会产生异常运行结果: 3.数据为空异常空指针(NullPointerExce......