`
welcomezhang
  • 浏览: 17787 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

BigDecimal使用常见误区

阅读更多
BigDecimal.valueOf(0.03f)

最近工作中一个同事用到了上述用法,感觉会丢失精度,但也不是特别确定,于是把BigDecimal这块使用过程中踩过的坑稍微整理一下。

 

使用误区一:初始化

        System.out.println(new BigDecimal("0.03"));
        System.out.println(new BigDecimal(3));
        System.out.println(new BigDecimal(0.03));

        System.out.println(BigDecimal.valueOf(3L));
        System.out.println(BigDecimal.valueOf(0.03));
        System.out.println(BigDecimal.valueOf(0.03f));

 

上述你能准确说出运行结果么?

0.03
3
0.0299999999999999988897769753748434595763683319091796875
3
0.03
0.029999999329447746

 

原理分析

最常用的标准构造器为:

public BigDecimal(String val);

另一个也基本一致:   

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

其他构造器使用不小心的话就可能产生问题,这块后续对java中的数值类型精度方面做个细致的学习和整理。

BigDecimal.valueOf(0.03f)这个数值不符合预期是float转double的时候丢失精度了,跟BigDecimal无关。

 

 

使用误区二:比较

        BigDecimal a = new BigDecimal("1.23");
        BigDecimal b = new BigDecimal("1.230");
        System.out.println(a.equals(b)); //false

结果竟不是预期的true。

原理分析 

equals是比较内容,自然不一样。BigDecimal的比较要用compareTo

        System.out.println(a.compareTo(b)); //0表示相等

 

 

使用误区三:运算 

        BigDecimal c = new BigDecimal("1.23");
        BigDecimal d = new BigDecimal("1.23");
        c.add(d);
        System.out.println(c);

 结果是2,46么?

显然不是,仍然是1.23

 

原理分析

BigDecimal加减乘除最终都返回的是一个新的BigDecimal对象,c.add(d);虽然做了加法操作,但是c并没有保存加操作后的值,正确的用法应该是c=c.add(d)。

 

 

使用误区四:除不尽

 

        System.out.println(new BigDecimal("100").divide(new BigDecimal("12")));
 结果直接抛异常了。
异常 如下:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

 

原理分析

BigDecimal的除法要养成习惯去设置精度,以免出现无限循环小数而抛异常。

 

new BigDecimal("100").divide(new BigDecimal("12").setScale(2, BigDecimal.ROUND_HALF_DOWN)

 这样写对么?wrong,正确写法如下:

new BigDecimal("100").divide(new BigDecimal("12"),2, BigDecimal.ROUND_HALF_DOWN);

 

 

再思考 

        System.out.println(0.99999999f == 1f); //true
        System.out.println(0.99999999 == 1); //false
 

note:关于java数值精度(double、float、BigDecimal)这块后续再整理一次,如果不明白细节,很容易犯错误。

2
0
分享到:
评论
4 楼 welcomezhang 2016-06-20  
jiangchao89911 写道
使用误区四:除不尽,这样写似乎也不对啊
System.out.println(new BigDecimal("100").divide(new BigDecimal("12").setScale(2, BigDecimal.ROUND_HALF_DOWN)));

多谢提醒,应该是这样
        System.out.println(new BigDecimal("100").divide(new BigDecimal("12"),2, BigDecimal.ROUND_HALF_DOWN));
3 楼 jiangchao89911 2016-06-17  
使用误区四:除不尽,这样写似乎也不对啊
System.out.println(new BigDecimal("100").divide(new BigDecimal("12").setScale(2, BigDecimal.ROUND_HALF_DOWN)));
2 楼 welcomezhang 2016-06-15  
string2020 写道
System.out.println(new BigDecimal(0.03));
结果为啥是:
0.0299999999999999988897769753748434595763683319091796875 

涉及到精度丢失及bigdecimal的构造原理,不太好解释,建议debug看一下
1 楼 string2020 2016-06-15  
System.out.println(new BigDecimal(0.03));
结果为啥是:
0.0299999999999999988897769753748434595763683319091796875 

相关推荐

    Java解惑(中文)

    ### Java解惑:常见误区与解答 #### 一、判断奇数的方法问题 **知识点概述:** 本节讨论了一个常见的编程误区,即如何正确判断一个整数是否为奇数。通常,开发人员会认为可以通过模运算(%)来判断一个整数是否能...

    java解惑.pdf

    本文详细探讨了Java中关于奇数检测和浮点数运算的常见误区。通过对这些陷阱的理解与规避,我们可以编写出更加可靠和高效的代码。在进行货币计算时,建议优先考虑使用 `BigDecimal` 类来避免精度问题。同时,在设计...

    Java解惑.pdf

    ### Java解惑:深入理解Java中的谜题与陷阱 #### 表达式谜题:奇数判断误区 ...采用正确的数据类型和算法,如使用位操作优化奇数判断,以及使用`BigDecimal`进行货币计算,可以帮助我们编写更可靠、更高效的代码。

    1222-张国旗-JAVA陷阱.rar

    对于金融计算等高精度需求,可以使用BigDecimal类。 以上只是Java编程中可能遇到的部分陷阱,实际的PPT可能还涵盖了更多细节和具体案例。学习和理解这些陷阱可以帮助开发者编写更加健壮、高效的代码,避免不必要的...

    Java解惑(中文版)[JAVA的细节]

    ### Java解惑(中文版)[JAVA的细节]:解析编程中的常见误区 #### 知识点一:取余操作符的特殊行为 **标题描述**:“根据JAVA编程中常犯的错误,针对每个错误编辑了一个实例,精细地讲解了编程时应当注意的事”。 *...

    不可不知道的10个java谎言

    在Java编程中,有些常见的误解可能...了解这些Java编程中的常见误区,有助于提高代码质量,避免不必要的问题,并在面试或实际开发中展现出更深入的理解。对于开发者来说,持续学习和纠正这些“谎言”是提升技能的关键。

    关于Java的10个谎言

    关于Java的10个常见误解: 1. System.exit(0)不会跳过finally块的执行。这个误区源自对System.exit(0)的理解不准确。实际上,当调用System.exit(0)时,整个JVM会被立即终止,包括任何正在运行的线程。但是,如果在...

Global site tag (gtag.js) - Google Analytics