使用 double 计算薪酬,我差点就凉凉了

估计大家都知道使用 double 做运算会出现精度问题,虽然我也知道,但是我还是想去试一下😂,最后做完了也没见出现精度问题,当时心里还暗爽,这都没问题呀,搞那么多花里胡哨的东西干啥。

直到第二天我看到这个计算结果:

还好现在发现了,要是等部署到用户那边才发现,我估计就真的凉凉了😭

不作就不会死,以后是不敢浪。

 

 然后我就找到了 BigDecimal

  

先看一个简单的例子:

BigDecimal a1 = new BigDecimal("1");
BigDecimal a2 = new BigDecimal("25");

BigDecimal result1 = a1.add(a2); // 加
BigDecimal result2 = a1.subtract(a2); // 减
BigDecimal result3 = a1.multiply(a2); // 乘
BigDecimal result4 = a1.divide(a2); // 除

System.out.println("加" + result1.toString());
System.out.println("减" + result2.toString());
System.out.println("乘" + result3.toString());
System.out.println("除" + result4.toString());

 

 提示:如果 a1.divide(a2) 相除不能得到确切的商,则会抛出一个ArithmeticException 。

如:1 / 3

 这时就要用这个方法了:

 

我们可以看到后面还有一个参数:根据上下文设置进行舍入。

API 中可以看到一共有八种舍入:

1、ROUND_UP

舍入模式从零开始。 始终在非零丢弃分数之前增加数字。 请注意,该舍入模式不会降低计算值的大小。

2、ROUND_DOWN

舍入模式向零舍入。 不要在丢弃的分数之前递增数字(即截断)。 请注意,该舍入模式不会增加计算值的大小。

3、ROUND_CEILING

如果BigDecimal为正,则表现为ROUND_UP ; 如果为负,则表现为ROUND_DOWN 。 请注意,舍入模式不会降低计算值。

4、ROUND_FLOOR

如果BigDecimal为正,则表现为ROUND_DOWN ; 如果为负,表现为ROUND_UP 。 请注意,舍入模式不会增加计算值。

5、ROUND_HALF_UP

四舍五入模式

6、ROUND_HALF_DOWN

五舍六入模式

7、ROUND_HALF_EVEN

就是小数第一位 大于5 ,小于5 舍去,等于 5 就看 左边的数是否为奇数,是奇数 ,否则 舍去

        BigDecimal a1 = new BigDecimal("4");
        BigDecimal a2 = new BigDecimal("5");
        BigDecimal a3 = new BigDecimal("6");

        BigDecimal b1 = new BigDecimal("14");
        BigDecimal b2 = new BigDecimal("15");
        BigDecimal b3 = new BigDecimal("16");

        BigDecimal c1 = new BigDecimal("24");
        BigDecimal c2 = new BigDecimal("25");
        BigDecimal c3 = new BigDecimal("26");

        BigDecimal ra1 = a1.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);
        BigDecimal ra2 = a2.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);
        BigDecimal ra3 = a3.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);

        BigDecimal rb1 = b1.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);
        BigDecimal rb2 = b2.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);
        BigDecimal rb3 = b3.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);

        BigDecimal rc1 = c1.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);
        BigDecimal rc2 = c2.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);
        BigDecimal rc3 = c3.divide(new BigDecimal("10"),BigDecimal.ROUND_HALF_EVEN);

        System.out.println("结果 0.4 ---- " + ra1.toString());
        System.out.println("结果 0.5 ---- " + ra2.toString());
        System.out.println("结果 0.6 ---- " + ra3.toString());

        System.out.println("结果 1.4 ---- " + rb1.toString());
        System.out.println("结果 1.5 ---- " + rb2.toString());
        System.out.println("结果 1.6 ---- " + rb3.toString());

        System.out.println("结果 2.4 ---- " + rc1.toString());
        System.out.println("结果 2.5 ---- " + rc2.toString());
        System.out.println("结果 2.6 ---- " + rc3.toString());

 

8、ROUND_UNNECESSARY

舍入模式来确定所请求的操作具有精确的结果,因此不需要舍入。 如果在产生不精确结果的操作上指定了舍入模式,则抛出ArithmeticException 。

上面相除的结果都是保留整数,那我要保留后两位小数怎么搞?

提示:ROUND_HALF_DOWN 这个五舍六入模式 和 第七个 ROUND_HALF_EVEN 有一个小细节问题

ROUND_HALF_EVEN :舍入方式是等于 5 就看 左边的数是否为奇数,是奇数 ,否则 舍去

如果你想做完运算后再保留小数:setScale 方法

 

计算社保总要比较大小吧,毕竟有缴纳最大最小基数嘛!

比较大小方法:compareTo

基本上已经了解的差不多了,回归正题看是不是真的没有精度问题。

如果我这里说有精度问题,估计我要被打死吧😂

但我还是要说,确实还有精度问题😄,是使用 double 构造方法有问题,String 就没问题。

        String s1 = "0.444";
        String s2 = "0.445";
        BigDecimal a1 = new BigDecimal(s1);
        BigDecimal a2 = new BigDecimal(s2);

        double d3 = 0.444;
        double d4 = 0.445;
        BigDecimal a3 = new BigDecimal(d3);
        BigDecimal a4 = new BigDecimal(d4);

        System.out.println(a1.multiply(a2));
        System.out.println(a3.multiply(a4));

 

小伙伴们记住了吗?要用 String 、 要用 String 、要用 String ;重要的事情说三遍。

 

最后:转成对应的类型方法,转 String 类型直接 toString() 就好。

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值