You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS实现收银机找零逻辑时循环跳过面额元素的问题排查

收银机找零函数遍历跳面额问题排查

问题描述

编写目标为拆解找零金额到对应货币面额、返回找零完成后更新的收银机余额的函数,当前仅在收银机对应起始面额库存充足时可正常运行:

  • 测试用例找零金额:[10, 4, 0.5, 0.05]
  • 预期逻辑:若收银机无10美元面额钞票,循环顺延检查5美元面额是否可用于找零,依次向下遍历更小面额
  • 实际异常:循环直接跳过中间面额,跳转至1美元面额处理
  • 前置约定:面额遍历起始索引已预先计算完成:
    • 10美元遍历起始索引为2(该索引前所有面额均大于10)
    • 4美元遍历起始索引为4(对应收银机数组中1美元面额的索引)
    • 其余面额起始索引按相同规则推导

问题复现代码

let change = [ 10, 4, 0.5, 0.05 ]
let denomin = [ 100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01 ]
let register = [ 100, 60, 0, 55, 90, 4.25, 3.1, 2.05, 1.01 ]
let idx = [ 2, 4, 5, 7 ]

function test(ch, reg, idx) {
    for (let x of ch) {
        for (let i = idx[ch.indexOf(x)]; i < reg.length; i++) {
            if (reg[i] - x >= 0) {
                reg[i] -= x
                break;
            } else if (reg[i] - x < 0) {
                i++
            }
        }
    }
    return reg = reg.map(a => Number(a.toFixed(2)))
}

console.log(test(change, register, idx))

根因分析

核心逻辑错误共2点,直接导致跳面额问题:

  1. 内层循环重复递增索引:for循环的循环头已经定义每次迭代结束自动执行i++,当当前面额库存不足(进入reg[i] - x < 0分支)时,代码又手动执行了一次i++,相当于单次循环i总共加2,直接跳过相邻的下一个面额。
    以处理第一个找零金额10为例:起始i=2(对应10美元面额,库存为0),进入else if分支手动i变为3,循环头迭代再执行i变为4,直接跳过i=3对应的5美元面额,落到i=4的1美元位置,和观测到的异常现象完全吻合。
  2. 隐含逻辑隐患:当前判断仅校验对应面额的总库存是否大于待找金额,没有结合denomin面额数组计算当前面额最多可使用的张数/总金额,无法正确支持非整倍数面额凑整的场景;另外用ch.indexOf(x)获取索引起始值的写法,在找零数组存在重复金额时会永远返回第一个匹配项的索引,导致起始索引计算错误。

修复后代码

let change = [10, 4, 0.5, 0.05]
let denomin = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01]
let register = [100, 60, 0, 55, 90, 4.25, 3.1, 2.05, 1.01]
let idx = [2, 4, 5, 7]

function test(ch, reg, idx) {
    for (let x of ch) {
        let remain = x
        // 移除手动i++逻辑,避免跳索引
        for (let i = idx[ch.indexOf(x)]; i < reg.length && remain > 0; i++) {
            const faceValue = denomin[i]
            // 计算当前面额最多可抵扣的金额
            const deduct = Math.min(reg[i], Math.floor(remain / faceValue) * faceValue)
            if (deduct > 0) {
                reg[i] = Number((reg[i] - deduct).toFixed(2))
                remain = Number((remain - deduct).toFixed(2))
            }
        }
    }
    return reg.map(a => Number(a.toFixed(2)))
}

console.log(test(change, register, idx))
// 输出:[100, 60, 0, 45, 89, 3.75, 3.1, 2, 1.01]

修复逻辑说明:处理单笔找零金额时新增剩余待找金额变量,遍历到每个面额时计算该面额最多可抵扣的金额,扣减后更新剩余待找金额,直到剩余待找金额为0再跳出循环,同时移除手动递增i的错误逻辑,避免跳面额。


内容的提问来源于stack exchange,提问作者Qaqli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:12:36