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

为什么JavaScript收银机找零函数的change变量会出现异常数值

问题排查结果

1. 核心原因:JavaScript浮点数精度丢失

JavaScript采用双精度浮点数存储数值,小数无法被精确二进制编码,多次加减运算后会出现精度偏移,比如0.1 + 0.2结果为0.30000000000000004,你看到的奇怪change值就是这个特性导致的。你的测试用例初始找零是0.6,多次减面值后就会出现类似0.09999999999999987的异常值。

2. 逻辑判断错误

你的条件判断存在三处逻辑错误,会导致找零流程无法按预期执行:

  • 条件change < cid[i][1]逻辑错误:你需要判断的是「当前币种的剩余总额足够支取至少一张该面值货币」,而非「剩余找零小于当前币种总额」,比如找零10元时,10大于QUARTER的总金额4.25,但你依然可以用QUARTER找零,这个条件会错误跳过可用面值。
  • 条件change > money[cid[i][0]]缺少等于判断:当剩余找零刚好等于当前面值时,该条件不成立,无法完成最后一次扣减,会进入死循环。
  • 缺少边界校验:当i递减到-1时,依然会访问cid[i]造成数组越界,同时如果无可用面值找零时会进入死循环。

修复方案
  1. 所有金额统一转为整数(单位为分)计算,彻底避免浮点数精度问题
  2. 修正条件判断逻辑,补充边界校验
    修复后代码示例:
function checkCashRegister(price, cash, cid) {
  // 所有金额转成分,转为整数计算
  let change = Math.round((cash - price) * 100)
  const money = {
    'PENNY': 1,
    'NICKEL':5,
    'DIME':10,
    'QUARTER':25,
    'ONE':100,
    'FIVE':500,
    'TEN':1000,
    'TWENTY':2000,
    'ONE HUNDRED':10000
  }
  // cid也转成整数
  const cidCent = cid.map(item => [item[0], Math.round(item[1] * 100)])
  console.log(change/100, 'start')
  let i = 8
  while(change > 0) {
    // 边界校验,没有可用面值时跳出
    if (i < 0) {
      console.log('无足够零钱找零')
      break
    }
    const faceVal = money[cidCent[i][0]]
    const cidTotal = cidCent[i][1]
    // 修正判断条件:面值小于等于找零,且抽屉有该面值的钱
    if (faceVal <= change && cidTotal >= faceVal) {
      console.log(cidCent[i][0], 'cid')
      console.log(faceVal/100, 'money')
      change -= faceVal
      cidCent[i][1] -= faceVal // 扣减抽屉里的钱
      console.log(change/100, 'change')
      i = 8 // 重置为最大面值重新遍历
    }
    i--
  }
}

checkCashRegister(19.4, 20,
[["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,提问作者Chris H.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 03:15:03