JS实现收银找零算法:从面额数组扣减使找零总额恰好归零
收银机找零功能逻辑修复方案
现有代码核心问题
- 面额遍历逻辑错误:内置面额数组从最小面额0.01升序排列,找零未遵循优先使用大面额的现实逻辑,通过
unshift插入符合条件面额的处理顺序混乱,且完全没有做库存金额校验 - 浮点数运算精度风险:直接对小数做加减计算,JS本身的浮点数精度缺陷会导致剩余找零额计算出现偏差,比如0.1+0.2≠0.3的经典问题
- 输出格式不符合要求:当前返回的
myArr2存储的是每次扣减后的剩余找零金额,不是实际付出的面额值,和预期输出结构完全不符 - 扣减逻辑缺失:没有循环判断当前面额最多可以用多少张,只要面额小于初始找零额就直接加入数组,完全不考虑扣减后剩余金额是否为负、库存是否足够
实现逻辑参考
- 优先把所有金额统一乘以100转为整数(按分计算),从根源规避浮点数运算精度问题
- 面额配置表按面额值从大到小倒序排列,遍历的时候优先匹配大面额,符合日常收银找零逻辑
- 遍历每个面额时,同时校验两个条件:当前剩余待找零金额大于等于单张面额值、收银机内该面额的剩余库存金额大于0
- 满足条件时循环扣减:每次扣减1张当前面额,同步更新剩余待找零额、该面额剩余库存、累计当前面额的使用总金额,直到不满足上述两个条件时,再切换到下一个更小的面额
- 所有面额遍历完成后,判断剩余待找零额是否为0,为0则返回收集到的找零面额数组,不为0说明现有库存无法凑出刚好的找零金额
修复后可运行代码
function checkCashRegister(price, cash, cid) { // 待找零金额转成整数(单位:分) let changeRemain = Math.round((cash - price) * 100); // 面额配置从大到小排序,单位统一转成分 const denominationList = [ ["ONE HUNDRED", 10000], ["TWENTY", 2000], ["TEN", 1000], ["FIVE", 500], ["ONE", 100], ["QUARTER", 25], ["DIME", 10], ["NICKEL", 5], ["PENNY", 1] ]; // 收银机库存转成整数分存储 const stockMap = {}; cid.forEach(([denominationName, amount]) => { stockMap[denominationName] = Math.round(amount * 100); }); const changeResult = []; for (const [name, unitValue] of denominationList) { let currentDenominationTotal = 0; // 尽可能多用当前面额找零 while (changeRemain >= unitValue && stockMap[name] > 0) { changeRemain -= unitValue; stockMap[name] -= unitValue; currentDenominationTotal += unitValue; } // 当前面额有使用的话,转回元单位加入结果数组 if (currentDenominationTotal > 0) { changeResult.push(currentDenominationTotal / 100); } } // 刚好凑齐找零返回结果,否则返回库存不足提示 return changeRemain === 0 ? changeResult : "收银机库存不足,无法完成找零"; } // 测试用例1:消费70元支付100元,找零30元,输出 [20, 10] console.log(checkCashRegister(70, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])); // 测试用例2:找零5.5元,输出 [5, 0.5] console.log(checkCashRegister(94.5, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]));
内容的提问来源于stack exchange,提问作者CRISVOSS
相关产品推荐
相关产品推荐

