收银台JavaScript代码功能异常:无法正确拆分找零面额
收银台找零面额拆分问题修复
问题说明
这款简易收银台需要实现以下功能:
- 计算顾客支付金额与商品价格的找零
- 找零前判断:若应找零金额大于收银机抽屉(cid)内可用现金,状态为
INSUFFICIENT_FUNDS;若足够则为OPEN - 状态为
OPEN时,找零需按抽屉内面额从大到小拆分并显示
当前代码存在问题:当应找零8.25美元时,预期显示Status: OPEN Five: $5, One: $3, Quarter: $0.25,但实际无法正确拆分面额。
错误原因
原代码中计算可用面额数量的逻辑错误:使用抽屉内该面额的总金额而非单张面额值来计算可找零数量,导致无法正确拆分出对应面额的金额。
修复后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Manny Cash Register</title> <link rel="stylesheet" href=""> </head> <body> <main> <form> <h1>Manny Cash Register</h1> <div id="change-due" class="result-div"></div> <div class="cash-input"> <label for="cash">Enter Cash From Customer:</label> <input id="cash" type="number" step="0.01" /> <button type="submit" id="purchase-btn">Purchase</button> </div> <div class="total">Total: $3.26</div> </form> <div class="cid"> <h4>Change in Drawer</h4> <div id="cid-display"></div> </div> </main> <script> const changeDue = document.getElementById("change-due"); const cash = document.getElementById("cash"); const purchaseBtn = document.getElementById("purchase-btn"); // 商品价格 let price = 3.26; // 收银机抽屉初始现金,格式:[面额名称, 总金额] let cid = [ ["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100] ]; // 定义各面额的单张价值 const denominationValues = { "PENNY": 0.01, "NICKEL": 0.05, "DIME": 0.1, "QUARTER": 0.25, "ONE": 1, "FIVE": 5, "TEN": 10, "TWENTY": 20, "ONE HUNDRED": 100 }; purchaseBtn.addEventListener("click", (e) => { e.preventDefault(); // 计算应找零金额,转换为浮点数避免精度问题 let change = parseFloat(cash.value) - price; let changeStatus = ""; let changeArray = []; // 处理支付金额不足的情况 if (parseFloat(cash.value) < price) { alert("Customer does not have enough money to purchase the item"); return; } // 处理刚好支付的情况 if (parseFloat(cash.value) === price) { changeDue.textContent = "No change due - customer paid with exact cash"; return; } // 计算抽屉内总现金 let totalCid = parseFloat(cid.reduce((acc, curr) => acc + curr[1], 0).toFixed(2)); // 判断抽屉现金是否足够找零 if (change > totalCid) { changeStatus = "INSUFFICIENT_FUNDS"; } else { changeStatus = "OPEN"; let remainingChange = parseFloat(change.toFixed(2)); // 从大到小遍历面额 for (let i = cid.length - 1; i >= 0; i--) { const denomName = cid[i][0]; const denomTotal = cid[i][1]; const denomValue = denominationValues[denomName]; // 计算该面额最多能找零的数量:不超过剩余找零所需,也不超过抽屉内现有数量 const maxNeeded = Math.floor(remainingChange / denomValue); const maxAvailable = Math.floor(denomTotal / denomValue); const count = Math.min(maxNeeded, maxAvailable); if (count > 0) { const amountToGive = parseFloat((count * denomValue).toFixed(2)); // 添加到找零数组 changeArray.push([denomName, amountToGive]); // 更新剩余找零金额 remainingChange = parseFloat((remainingChange - amountToGive).toFixed(2)); // 更新抽屉内该面额的剩余金额 cid[i][1] = parseFloat((denomTotal - amountToGive).toFixed(2)); } // 剩余找零为0时提前退出循环 if (remainingChange <= 0.001) break; } // 如果仍有剩余找零无法拆分,标记为资金不足 if (remainingChange > 0.001) { changeStatus = "INSUFFICIENT_FUNDS"; changeArray = []; } } // 渲染找零结果 let changeString = changeArray.map(item => `${item[0]}: $${item[1]}`).join(", "); if (changeStatus === "INSUFFICIENT_FUNDS") { changeDue.textContent = `Status: ${changeStatus}`; } else { changeDue.textContent = `Status: ${changeStatus} ${changeString}`; } cash.value = ""; }); </script> </body> </html>
修复要点
- 新增面额单张值定义:创建
denominationValues对象,明确每个面额的单张价值,用于正确计算可找零数量 - 修正找零数量计算逻辑:分别计算剩余找零所需的最大面额数量、抽屉内可用的最大面额数量,取两者最小值作为实际找零数量
- 优化精度处理:全程使用
parseFloat(...toFixed(2))避免浮点数精度误差 - 提前终止循环:剩余找零为0时提前退出循环,提升性能
- 完善结果渲染:资金不足时仅显示状态,避免空字符串干扰
内容的提问来源于stack exchange,提问作者anoghena kanoba
相关产品推荐
相关产品推荐

