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