欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚

程序员文章站 2022-05-14 20:50:09
Hello,搭嘎吼啊,我是渣渣灰~转眼就周四了呢~今天也是充满希望的一天哦~( ˶˙º˙˶ )୨最近在做一个金融项目,涉及到金额计算,最开始我还很单纯,不管小数还是整数都用的是Double,在自己测试的时候也挺好的。金融项目也不是那么难嘛~ʕง•ᴥ•ʔง咕噜咕噜的就把代码敲了一大堆,突然感觉到后背一凉,通过显示器的反射,看到了一个令人恐惧的脸庞!老大:小苏啊,你家境怎样?我:(害)小…小康,咋了老大~ ⚆ꆚ⚆老大:那你用Double来做计算,中间造成的误差你来承担吗!什么!Double...

Hello,搭嘎吼啊,我是渣渣灰~
转眼就周四了呢~
今天也是充满希望的一天哦~( ˶˙º˙˶ )୨
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
最近在做一个金融项目,涉及到金额计算,最开始我还很单纯,不管小数还是整数都用的是Double,在自己测试的时候也挺好的。
金融项目也不是那么难嘛~ʕง•ᴥ•ʔง
咕噜咕噜的就把代码敲了一大堆,突然感觉到后背一凉,通过显示器的反射,看到了一个令人恐惧的脸庞!
老大:小苏啊,你家境怎样?
我:(害)小…小康,咋了老大~ ⚆ꆚ⚆
老大:那你用Double来做计算,中间造成的误差你来承担吗!
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
什么!Double计算会造成误差?不会吧不会吧,赶快打开IDEA测试一下!

 public static void main(String[] args) {

        System.out.println(0.05 + 0.01);

    }

结果肯定是0.06啦~计算机程序怎么可能这么傻,这都会算错✧( •˓◞•̀ )
结果却是…
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
怎么肥四!这后面的东西哪来的!一定是BUG了,对!一定是!换一个数值试一下!(•̀へ•́╮)

public static void main(String[] args) {

        System.out.println(4.015 * 100);

    }

预期的结果401.5
结果…
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
发动!《面向百度编程》

Java中的简单浮点数类型float和double不能够进行运算。不仅仅是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。
可以参考:计算机组成原理:浮点精度运算不精确的原因

JAVA到底用什么来计算金额呢?

在《Effective Java》这本书中提到,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal

BigDecimal一共有4个构造方法,我们不关心用BigInteger来构造的那两个,那么还有两个,它们是
BigDecimal(double val)
BigDecimal(String val)
注意! 在参数为double的构造方法上有这么一段话

Note: the results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances nonwithstanding. The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal(".1") is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.

也就是说,官方更建议我们使用String参数的构造方法
本着实践是检验真理的唯一标准,验证一下官方说的到底是不是这么一回事~༼ つ ◕_◕ ༽つ

public static void main(String[] args) {

        double d = 1.23;
        BigDecimal d1 = new BigDecimal(d);
        System.out.println("d1 = " + d1);

        String s = "1.23";
        BigDecimal s1 = new BigDecimal(s);
        System.out.println("s1 = " + s1);

    }

执行结果
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
这相差是有点大哈…ᕙ(⇀‸↼‶)ᕗ
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
但是想一下,每次做运算需要先将Double转为String,如果有多个Double就要转多次…
蛇精病啊!(:τ」∠)
经过对BigDecimal这个类的摸索,发现了一个非常好用的静态方法valueOf
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
这个方法在底层也是帮助我们自动的把double转为了String类型,我们只需要调用这个方法来获取BigDecimal对象就好了,不用每次都new
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
实践出真知,来试一下~ヽ(•̀ω•́ )ゝ

public static void main(String[] args) {

        double d = 1.23;
        BigDecimal d1 = new BigDecimal(d);
        System.out.println("d1 = " + d1);

        BigDecimal d2 = BigDecimal.valueOf(d);
        System.out.println("d2 = " + d2);

        String s = "1.23";
        BigDecimal s1 = new BigDecimal(s);
        System.out.println("s1 = " + s1);

    }

控制台打印的结果
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
肥肠NICE!是我们预期的结果,精度问题我们解决了,下面就要真正的开始进行小学的加减乘除了~੭ ˙ᗜ˙ )੭
各位看官有没有昏昏入睡呢?
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
加法:add(BigDecimal augend)

public static void main(String[] args) {

        double d = 1.23;
        BigDecimal d2 = BigDecimal.valueOf(d);
        System.out.println("d2 = " + d2);

        String s = "1.23";
        BigDecimal s1 = new BigDecimal(s);
        System.out.println("s1 = " + s1);

        BigDecimal add = d2.add(s1);
        System.out.println("add = " + add);

    }

控制台
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
减法:subtract(BigDecimal subtrahend)

public static void main(String[] args) {

        double d = 1.23;
        BigDecimal d2 = BigDecimal.valueOf(d);
        System.out.println("d2 = " + d2);

        String s = "1.23";
        BigDecimal s1 = new BigDecimal(s);
        System.out.println("s1 = " + s1);

        BigDecimal add = d2.add(s1);
        System.out.println("add = " + add);

        BigDecimal subtract = add.subtract(s1);
        System.out.println("subtract = " + subtract);

    }

控制台
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
乘法: multiply()

public static void main(String[] args) {

        double d = 1.23;
        BigDecimal d2 = BigDecimal.valueOf(d);
        System.out.println("d2 = " + d2);

        String s = "1.23";
        BigDecimal s1 = new BigDecimal(s);
        System.out.println("s1 = " + s1);

        BigDecimal add = d2.add(s1);
        System.out.println("add = " + add);

        BigDecimal subtract = add.subtract(s1);
        System.out.println("subtract = " + subtract);
		//乘100
        BigDecimal multiply = subtract.multiply(BigDecimal.valueOf(100));
        System.out.println("multiply = " + multiply);

    }

控制台
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
除法:divide()

除法需要指定保留几位小数,保留规则是什么(四舍五入)

现在把数据改为1.25,测试四舍五入

public static void main(String[] args) {

        double d = 1.25;
        BigDecimal d2 = BigDecimal.valueOf(d);
        System.out.println("d2 = " + d2);

        String s = "1.23";
        BigDecimal s1 = new BigDecimal(s);
        System.out.println("s1 = " + s1);

        BigDecimal add = d2.add(s1);
        System.out.println("add = " + add);

        BigDecimal subtract = add.subtract(s1);
        System.out.println("subtract = " + subtract);

        BigDecimal multiply = subtract.multiply(BigDecimal.valueOf(100));
        System.out.println("multiply = " + multiply);
        //除1000,保留2位小数,四舍五入
        BigDecimal divide = multiply.divide(BigDecimal.valueOf(1000),2, BigDecimal.ROUND_HALF_UP);
        System.out.println("divide = " + divide);

    }

控制台
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
现在大家都掌握了JAVA应该怎么做加减乘除了吧~(っ╹◡╹)ノ❀
你学废了吗?
学废了就点个赞吧~
荐
                                                        Java BigDecimalの食用方法,老大说我再用Double来进行数值的计算,造成的损失从我工资里扣!˚‧º·(˚ ˃̣̣̥⌓˂̣̣̥ )‧º·˚
球球了,点个赞吧~(。˘•ε•˘。) 我十拿九稳,少你一吻

本文地址:https://blog.csdn.net/weixin_46526674/article/details/107377364