Java中使用BigDecimal进行浮点数运算

 更新时间:2014年07月05日 14:20:39   投稿:junjie  
这篇文章主要介绍了Java中使用BigDecimal进行浮点数运算,需要的朋友可以参考下

最近研究了一下Java的浮点数计算问题,从网上查询了相关的资料,汇总并经过了一些整理和调试,最后完成此文,欢迎大家指出其中的错误和问题。
在Java中,float声明的变量是单精度浮点数,double声明的变量是双精度浮点数,顾名思义就是double型的实体占用内存空间是float的两倍。float是4个字节而double是8个字节。float和double类型的数据,无法精确表示计算结果,这是由于float和double是不精确的计算。大家可以通过下面代码可以看出来:

复制代码 代码如下:

public class Test
{
public static void main(String[] args)
{
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.3 / 100);
}
}


运行的结果为:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

要想获得理想的效果,我们可以尝试使用java.text.DecimalFormat格式化浮点数:
DecimalFormat可以按照一定的格式格式化数字,常用的格式化字符是#、0等。例:

复制代码 代码如下:

System.out.println(new java.text.DecimalFormat("0.00").format(3.125));
System.out.println(new java.text.DecimalFormat("0.00").format(3.135));


但是得到的结果是:
3.12
3.14

这是因为DecimalFormat是使用half-even 舍入(ROUND_HALF_EVEN),简单的说就是向当四舍五入的5的时候向最近的偶数靠。所以使用DecimalForamt也无法得到可靠的浮点数。最后我们可以考虑使用BigDecimal来获得更精确的计算:

BigDecimal提供了多个构造函数,和浮点数有关的有:

复制代码 代码如下:

BigDecimal(double val)  Translates a double into a BigDecimal.
BigDecimal(String val)  Translates the String repre sentation of a BigDecimal into a BigDecimal.

但是用double参数来创建对象得到不精确的值,只有通过String来创建对象才是最准确的。

例如:

复制代码 代码如下:

BigDecimal bd1=new BigDecimal(0.05);
System.out.println(bd1.toString());
BigDecimal bd2=new BigDecimal("0.05");
System.out.println(bd2.toString());

得到结果:

0.05000000000000000277555756156289135105907917022705078125
0.05

所以,我们最终需要使用String来创建对象,这样得到的结果才是最精确的。另外,如果是double数,我们还可以使用:BigDecimal.valueOf(double val),原因很简单,其JDK源码如下所示:

复制代码 代码如下:

public static BigDecimal valueOf(double val)
{
return new BigDecimal(Double.toString(val));
}

最后需要说明的是:BigDecimal的加减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigDecimal是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以a.add(b);虽然做了加法操作,但是a并没有保存加操作后的值,正确的用法应该是a=a.add(b)。

相关文章

  • Spring中propagation的传播机制详解

    Spring中propagation的传播机制详解

    这篇文章主要介绍了Spring中propagation的传播机制详解,要搞懂事务的传播机制,那么就要明白逻辑事务中各个事务的关系,才能彻底理解事务传播特性,在Spring事务中,各个逻辑事务的关系可以是并列、覆盖或包含,需要的朋友可以参考下
    2023-12-12
  • Java中ArrayList与顺序表的定义与实现方法

    Java中ArrayList与顺序表的定义与实现方法

    ArrayList是一个实现List接口的类,底层是动态类型顺序表,本质也就是数组,动态主要体现在它的扩容机制,下面这篇文章主要给大家介绍了关于Java中ArrayList与顺序表的定义与实现的相关资料,需要的朋友可以参考下
    2022-07-07
  • 23种设计模式(9) java桥接模式

    23种设计模式(9) java桥接模式

    这篇文章主要为大家详细介绍了java设计模式之桥接模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Springboot整合Gson报错问题解决过程

    Springboot整合Gson报错问题解决过程

    这篇文章主要介绍了Springboot整合Gson报错问题解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • SpringBoot Loki安装简介及实战思路

    SpringBoot Loki安装简介及实战思路

    这篇文章主要为大家介绍了SpringBoot Loki安装简介及实战思路详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪的相关资料
    2022-11-11
  • java Stream流常见操作方法(反射,类加载器,类加载,反射)

    java Stream流常见操作方法(反射,类加载器,类加载,反射)

    这篇文章主要介绍了java Stream流常见操作方法(反射,类加载器,类加载,反射),文章围绕主题展开详细的内容介绍,展开详细的内容介绍,具有一定参考价值,感兴趣的小伙伴可以参考一下
    2022-06-06
  • MyBatis-Plus中MetaObjectHandler没生效完美解决

    MyBatis-Plus中MetaObjectHandler没生效完美解决

    在进行测试时发现配置的MyMetaObjectHandler并没有生效,本文主要介绍了MyBatis-Plus中MetaObjectHandler没生效完美解决,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Java抽象类、继承及多态和适配器的实现代码

    Java抽象类、继承及多态和适配器的实现代码

    这篇文章主要介绍了Java抽象类、继承及多态和适配器的实现,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-06-06
  • Java学习教程之定时任务全家桶

    Java学习教程之定时任务全家桶

    这篇文章主要给大家介绍了关于Java学习教程之定时任务全家桶的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • MybatisX无法自动生成entity实体类的解决方法

    MybatisX无法自动生成entity实体类的解决方法

    本文主要介绍了MybatisX无法自动生成entity实体类的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06

最新评论