案例介绍
具体的内容是这样的:
编写一个程序,提示输入一个代表总钱数的双精度值,然后确定每种纸币和硬币需要的最少数量以达到输入的总钱数。
假设人民币种类如下:佰圆纸钞,伍拾圆纸钞,贰拾圆纸钞,拾圆纸钞,伍圆纸钞,壹圆硬币,伍角硬币,壹角硬币,壹分硬币。(提示:使用求模运算符,自上而下求得每种钱币的数量)。
例如,输入值为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;//佰圆纸钞; 100int bai = (int)(money / 10 /10 % 10);System.out.println(bai+" 张佰圆纸钞");// 去掉一百钞用掉的money = money - (100 * bai);System.out.println("----------剩余可换的钱:"+money);//伍拾圆纸钞;50int wushi =(int)( (money / 50));System.out.println(wushi+" 张伍拾圆纸钞");// 去掉五十钞用掉的money = money - (50 * wushi);System.out.println("----------剩余可换的钱:"+money);//贰拾圆纸钞;20int ershi =(int)( (money / 20) );System.out.println(ershi+" 张贰拾圆纸钞");// 去掉二十钞用掉的money = money - (20 * ershi);System.out.println("----------剩余可换的钱:"+money);//拾圆纸钞;10int shi =(int)( (money / 10) );System.out.println(shi+" 张贰拾圆纸钞");// 去掉十钞用掉的money = money - (10 * shi);System.out.println("----------剩余可换的钱:"+money);//伍圆纸钞;5int wu =(int)( (money / 5) );System.out.println(wu+" 张伍圆纸钞");// 去掉5钞用掉的money = money - (5 * wu);System.out.println("----------剩余可换的钱:"+money);//壹圆硬币;1int yi =(int)( (money / 1) );System.out.println(yi+" 张壹圆硬币");// 去掉1钞用掉的money = money - (1 * yi);System.out.println("----------剩余可换的钱:"+money);//伍角硬币;0.5int lindianwu =(int)( (money / 0.5) );System.out.println(lindianwu+" 张伍角硬币");// 去掉0.5钞用掉的money = money - (0.5 * lindianwu);System.out.println("----------剩余可换的钱:"+money);//壹角硬币;0.1int 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个壹分硬币。
反思
在输出打印剩余可换的钱的时候,可以看到,出现了特别长的小数
这是怎么回事呢
答案很明显,这是因为double类型,存在精度丢失的问题
那,有没有办法可以解决这个问题呢
精度丢失在Java中常见的两种解决方案
小数转整数
you know 蟹不肉
整数不存在精度问题,所以常用的方式是将涉及的浮点数转成整数。
而我们熟知的,int可容纳 -2147483648
到 2147483647
的数值
因此,这种方法,常常用在小型会计系统,而且,小型会计系统小数位是固定位数才有意义
比如 23.64元,小数位固定在两位
这个时候就可以把浮点数*100
转成整数,变成2364来计算
使用BigDecimal
大数字的精确计算就经常用到这个类: BigDecimal
唯一要注意的细节是:BigDecimal初始化时,你往构造器传入double类型数据还是会存在精度丢失
那咋办呢
那就把double用包装类Double转成String类型,把他变成String类型再传入BigDecimal构造器
兜兜转转真奇妙