likes
comments
collection
share

JavaSE 案例练习——精算师 double精度丢失解决思路

作者站长头像
站长
· 阅读数 27

案例介绍

具体的内容是这样的

编写一个程序,提示输入一个代表总钱数的双精度值,然后确定每种纸币和硬币需要的最少数量以达到输入的总钱数。

假设人民币种类如下:佰圆纸钞,伍拾圆纸钞,贰拾圆纸钞,拾圆纸钞,伍圆纸钞,壹圆硬币,伍角硬币,壹角硬币,壹分硬币。(提示:使用求模运算符,自上而下求得每种钱币的数量)。

例如,输入值为127.63元人民币,那么程序应当输出如下结果:

  • 1张佰圆纸钞;

  • 0张伍拾圆纸钞;

  • 1张贰拾圆纸钞;

  • 0张拾圆纸钞;

  • 1张伍圆纸钞;

  • 2个壹圆硬币;

  • 1个伍角硬币;

  • 1个壹角硬币;

  • 3个壹分硬币。

解题

思考

这题还是有思路的:

题干中说到:确定每种纸币和硬币需要的最少数量以达到输入的总钱数。

可以理解为:

  • 尽量用最大数值的钱币去找零钱
  • 那么我们应该从最大的钱币 开始 去扣掉这个数值
  • 程序的顺序 从最大的钱币 到最小的钱币,直到找完

操作

因此,可以编写如下的代码:


import java.util.Scanner;

public class countMoney {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("输入一个代表总钱数的双精度值,例如127.63");
        double money = sc.nextDouble();
//       double money = 127.63;

        //佰圆纸钞;  100
        int bai = (int)(money / 10 /10 % 10);
        System.out.println(bai+" 张佰圆纸钞");
        // 去掉一百钞用掉的
        money = money - (100 * bai);
        System.out.println("----------剩余可换的钱:"+money);


        //伍拾圆纸钞;50
        int wushi =(int)( (money / 50));
        System.out.println(wushi+" 张伍拾圆纸钞");
        // 去掉五十钞用掉的
        money = money - (50 * wushi);
        System.out.println("----------剩余可换的钱:"+money);


        //贰拾圆纸钞;20
        int ershi =(int)( (money / 20) );
        System.out.println(ershi+" 张贰拾圆纸钞");
        // 去掉二十钞用掉的
        money = money - (20 * ershi);
        System.out.println("----------剩余可换的钱:"+money);


        //拾圆纸钞;10
        int shi =(int)( (money / 10) );
        System.out.println(shi+" 张贰拾圆纸钞");
        // 去掉十钞用掉的
        money = money - (10 * shi);
        System.out.println("----------剩余可换的钱:"+money);


        //伍圆纸钞;5
        int wu =(int)( (money / 5) );
        System.out.println(wu+" 张伍圆纸钞");
        // 去掉5钞用掉的
        money = money - (5 * wu);
        System.out.println("----------剩余可换的钱:"+money);


        //壹圆硬币;1
        int yi =(int)( (money / 1) );
        System.out.println(yi+" 张壹圆硬币");
        // 去掉1钞用掉的
        money = money - (1 * yi);
        System.out.println("----------剩余可换的钱:"+money);


        //伍角硬币;0.5
        int lindianwu =(int)( (money / 0.5) );
        System.out.println(lindianwu+" 张伍角硬币");
        // 去掉0.5钞用掉的
        money = money - (0.5 * lindianwu);
        System.out.println("----------剩余可换的钱:"+money);
        //壹角硬币;0.1
        int yijiao =(int)( (money / 0.1) );
        System.out.println(yijiao+" 壹角硬币");
        // 去掉0.1钞用掉的
        money = money - (0.1 * yijiao);
        System.out.println("----------剩余可换的钱:"+money);
        //壹分硬币。0.01

        // 四舍五入技法
        //  String result = String.format("%.2f", a);
        String result = String.format("%.2f", money);
        //System.out.println(result);
        int yifen = (int)(Double.parseDouble(result) / 0.01);
        System.out.println(yifen+" 张壹角硬币");
    }
}


//编写一个程序,提示输入一个代表总钱数的双精度值,然后确定每种纸币和硬币需要的最少数量以达到输入的总钱数。
//假设人民币种类如下:佰圆纸钞,伍拾圆纸钞,贰拾圆纸钞,拾圆纸钞,伍圆纸钞,壹圆硬币,伍角硬币,壹角硬币,壹分硬币。(提示:使用求模运算符,自上而下求得每种钱币的数量)。
//例如,输入值为127.63元人民币,那么程序应当输出如下结果:
//1张佰圆纸钞;
//0张伍拾圆纸钞;
//1张贰拾圆纸钞;
//0张拾圆纸钞;
//1张伍圆纸钞;
//2个壹圆硬币;
//1个伍角硬币;
//1个壹角硬币;
//3个壹分硬币。

JavaSE 案例练习——精算师 double精度丢失解决思路

反思

在输出打印剩余可换的钱的时候,可以看到,出现了特别长的小数

这是怎么回事呢

答案很明显,这是因为double类型,存在精度丢失的问题

那,有没有办法可以解决这个问题呢

精度丢失在Java中常见的两种解决方案

小数转整数

you know 蟹不肉

整数不存在精度问题,所以常用的方式是将涉及的浮点数转成整数。

而我们熟知的,int可容纳 -2147483648 到 2147483647的数值

因此,这种方法,常常用在小型会计系统,而且,小型会计系统小数位是固定位数才有意义

比如 23.64元,小数位固定在两位

这个时候就可以把浮点数*100 转成整数,变成2364来计算

使用BigDecimal

大数字的精确计算就经常用到这个类: BigDecimal

唯一要注意的细节是:BigDecimal初始化时,你往构造器传入double类型数据还是会存在精度丢失

那咋办呢

那就把double用包装类Double转成String类型,把他变成String类型再传入BigDecimal构造器

兜兜转转真奇妙

JavaSE 案例练习——精算师 double精度丢失解决思路