Java找零计算程序数学逻辑错误修复咨询
问题排查与修复方案
我仔细看了你的代码和问题描述,发现两个关键错误导致找零逻辑出错:
错误1:分币找零的计算逻辑完全错误
你现在的代码把美元和分币拆分开独立计算找零,这忽略了一个核心场景:当支付的分币少于消费的分币时,需要从美元部分借1美元(即100分)来补全,而不是直接用centsPaid - centsOwed(这会得到负数,导致硬币计算全部错误)。
比如你的示例输入:消费11.33(11美元33分),支付15.00(15美元0分),分币部分0-33会得到-33,这显然不对,正确的做法应该是先计算总找零的分数,再拆分纸币和硬币。
错误2:printCoins方法的笔误
在printCoins方法中,你错误地使用了bills.charAt(i)来获取硬币数量,而不是coins.charAt(i),这直接导致了输出中出现--$0.25这类混乱内容。
修复后的完整代码
下面是修复后的代码,我调整了整体逻辑,改用总分数来计算找零,避免了浮点数精度问题和借位错误,同时修复了笔误:
import java.util.Scanner; class Main { public static void main(String[] args) { Scanner money = new Scanner(System.in); System.out.println(" "); System.out.println("Please enter the amount of the purchase followed by the amount of a payment, separated by a comma."); System.out.println(" "); System.out.print("Amount of Purchase, Amount of Payment: "); String input = money.nextLine(); int commaIndex = input.indexOf(","); // 解析消费和支付金额,转换为总分数(避免浮点数精度问题) double cost = Double.parseDouble(input.substring(0, commaIndex).trim()); double payment = Double.parseDouble(input.substring(commaIndex + 1).trim()); // 计算总找零分数,先转成long避免精度丢失 long totalChangeCents = Math.round(payment * 100) - Math.round(cost * 100); if (totalChangeCents < 0) { System.out.println("Payment amount is less than purchase cost!"); return; } // 拆分纸币和硬币部分 long dollarsChange = totalChangeCents / 100; long centsChange = totalChangeCents % 100; String billsString = billsChange(dollarsChange); String coinsString = coinsChange(centsChange); printBills(billsString); printCoins(coinsString); } static String billsChange(long dollarsReturned) { StringBuilder retString = new StringBuilder(); // 按面额从大到小计算 int[] denominations = {100, 50, 20, 10, 5, 1}; for (int denom : denominations) { int count = (int) (dollarsReturned / denom); retString.append(count); dollarsReturned -= count * denom; } return retString.toString(); } static String coinsChange(long centsReturned) { StringBuilder retString = new StringBuilder(); // 按面额从大到小计算 int[] denominations = {25, 10, 5, 1}; for (int denom : denominations) { int count = (int) (centsReturned / denom); retString.append(count); centsReturned -= count * denom; } return retString.toString(); } static void printBills(String bills) { StringBuilder printString = new StringBuilder(); String[] billNames = {"$100", "$50", "$20", "$10", "$5", "$1"}; for (int i = 0; i < bills.length(); i++) { char countChar = bills.charAt(i); if (countChar != '0') { printString.append(countChar).append("-").append(billNames[i]).append(" "); } } System.out.print(printString); } static void printCoins(String coins) { StringBuilder printString = new StringBuilder(); String[] coinNames = {"$0.25", "$0.10", "$0.05", "$0.01"}; for (int i = 0; i < coins.length(); i++) { char countChar = coins.charAt(i); // 修复:用coins而不是bills if (countChar != '0') { printString.append(countChar).append("-").append(coinNames[i]).append(" "); } } System.out.print(printString); } }
关键修改说明
- 改用总分数计算找零:将消费和支付金额转换为总分数(比如15.00就是1500分),直接计算总找零分数,避免了美元和分币分开计算的借位问题,同时也规避了浮点数的精度误差。
- 修复printCoins的笔误:把
bills.charAt(i)替换为coins.charAt(i),确保读取的是硬币数量字符串。 - 优化代码结构:用数组存储面额,减少重复代码,让逻辑更清晰。
- 增加异常判断:如果支付金额小于消费金额,直接提示错误,避免负数找零。
测试你的示例输入11.33,15.00,总找零是367分(3美元67分),输出将是:3-$1 2-$0.25 1-$0.10 1-$0.05 2-$0.01,完全符合预期。
内容的提问来源于stack exchange,提问作者snavelien
相关产品推荐
相关产品推荐

