首页 > 解决方案 > 为什么“if else 语句”不能正常工作?

问题描述

我在 freecodecamp 中做 JS 算法和数据结构项目,我被最后一个问题“收银机”困住了。我已经进行了一些编码,但我的代码没有通过所有测试。

问题的链接:https ://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register

我的代码没有通过 3 和 5 数字测试。在数字 3 中,输出几乎相同,但最后一部分 ["PENNY",0.03] 与输出不匹配。在数字 5 中,totalCidandcashback变量相等,但不返回“CLOSED”。如果它们相等,它应该返回状态“CLOSED”。

function checkCashRegister(price, cash, cid) {
  var cashback = (cash - price)
  var returnMoney = {
    status: "",
    change: []
  }
  var totalCid = cid.map(v => {
      return v[1]
    })
    .reduce((a, b) => {
      return a + b
    })
    .toFixed(2)
  console.log(cashback)
  console.log(totalCid)
  if (totalCid === cashback) {
    returnMoney.status = "CLOSED"
    returnMoney.change = cid
    return returnMoney
  } else if (totalCid < cashback) {
    returnMoney.status = "INSUFFICIENT_FUND"
    returnMoney.change = []
    return returnMoney
  } else {
    var denomValue = [{
        bill: "ONE HUNDRED",
        val: 100
      },
      {
        bill: "TWENTY",
        val: 20
      },
      {
        bill: "TEN",
        val: 10
      },
      {
        bill: "FIVE",
        val: 5
      },
      {
        bill: "ONE",
        val: 1
      },
      {
        bill: "QUARTER",
        val: 0.25
      },
      {
        bill: "DIME",
        val: 0.10
      },
      {
        bill: "NICKEL",
        val: 0.05
      },
      {
        bill: "PENNY",
        val: 0.01
      }
    ]
    var newCidArray = [];
    var currVal = 0;
    for (let i = 0; i < denomValue.length; i++) {
      while (cashback >= denomValue[i].val && currVal < cid[8 - i][1]) {
        cashback -= denomValue[i].val.toFixed(2);
        currVal += denomValue[i].val;
      }

      if (currVal > 0) {
        newCidArray.push([denomValue[i].bill, currVal]);
      }
      currVal = 0; // reset current value (currVal) to zero after the loop has completed
    }
    returnMoney.status = "OPEN"
    returnMoney.change = newCidArray
    return returnMoney

  }

}
console.log(checkCashRegister(19.5, 20, [
  ["PENNY", 0.5],
  ["NICKEL", 0],
  ["DIME", 0],
  ["QUARTER", 0],
  ["ONE", 0],
  ["FIVE", 0],
  ["TEN", 0],
  ["TWENTY", 0],
  ["ONE HUNDRED", 0]
]))

标签: javascript

解决方案


您的代码中共有 3 个问题。

@trincot 指出了第一个:toFixed()返回一个字符串,您无法将其与===数字进行比较。

第二个是即使抽屉里的现金多于预期的零钱,你也可能会INSUFFICIENT_FUNDS因为无法拆分你所拥有的纸币(纸币,用英式英语)和硬币而陷入困境。这意味着在算法结束时,您必须检查更改是否相加。

第三个,也是主要的一个,来自使用浮点数。如果您单击“在您的代码下运行代码片段”,您可以看到更改将是0.49000000000000027几美分。

摆脱浮点沼泽的唯一安全方法是将所有内容转换为整数。因此,除了解决前两个问题之外,我所做的就是在脚本中将美元转换为便士。尽管如此,我还是尽量不要过多地改变你的脚本。

function checkCashRegister(price, cash, cid) {
  // P stands for pennies
  var cidP = cid.map(v => [v[0], Math.round(v[1] * 100)])
  var priceP = Math.round(price * 100)
  var cashP  = Math.round(cash * 100)
  var cashbackP = (cashP - priceP)
  var returnMoney = {
    status: "",
    change: []
  }
  var totalCidP = cidP.map(v => {
      return v[1]
    })
    .reduce((a, b) => {
      return a + b
    })
  if (totalCidP === cashbackP) {
    returnMoney.status = "CLOSED"
    returnMoney.change = cid
    return returnMoney
  } else if (totalCidP < cashbackP) {
    returnMoney.status = "INSUFFICIENT_FUNDS"
    returnMoney.change = []
    return returnMoney
  } else {
    var denomValueP = [
      {bill: "ONE HUNDRED", val: 10000},
      {bill: "TWENTY", val: 2000},
      {bill: "TEN", val: 1000},
      {bill: "FIVE", val: 500},
      {bill: "ONE", val: 100},
      {bill: "QUARTER", val: 25},
      {bill: "DIME", val: 10},
      {bill: "NICKEL", val: 5},
      {bill: "PENNY", val: 1}
    ]
    var changeArray = [];
    for (let i = 0; i < denomValueP.length; i++) {
      var currValP = 0;
      while (cashbackP >= denomValueP[i].val && currValP < cidP[8 - i][1]) {
        cashbackP -= denomValueP[i].val;
        currValP  += denomValueP[i].val;
      }
      if (currValP > 0) {
        changeArray.push([denomValueP[i].bill, currValP / 100]);
      }
    }
    if (cashbackP === 0) {
      returnMoney.status = "OPEN"
      returnMoney.change = changeArray
    } else {
      returnMoney.status = "INSUFFICIENT_FUNDS"
      returnMoney.change = []
    }
    return returnMoney
  }
}

至于为什么Math.round()需要这些,试试这个:

4567.89 * 100 === 456789  // => false

编辑

您要求澄清代码中的最后一个 if-else。freecodecamp的第四段说:

{status: "INSUFFICIENT_FUNDS", change: []}如果抽屉里的现金少于应找的零钱,或者您不能退回确切的零钱,请退货。

如果你到了算法的末尾cashbackP,并且你一直在减少你添加到找零中的每张钞票或硬币,但还没有变为零,这意味着找零不完整,你处于我强调的情况.


推荐阅读