【问题标题】:Javascript: Building a cash register function and having trouble with floating pointsJavascript:构建收银机功能并遇到浮点问题
【发布时间】:2018-11-30 04:38:42
【问题描述】:

我为 freecodecamp 构建的收银机功能设置了以下代码。我注意到浮点数的几个问题,所以每次对浮点数进行计算时,我都会听取其他人的建议并添加 .toFixed(2) 。我目前遇到的两个问题是:

  1. 我正在创建 cid 的副本,这样我就不会对其进行修改,并且可以在抽屉解析为关闭时将其返回,但是 cid 会与 cidCopy 一起被修改,即使我对其进行了切片并且从未修改过它李>
  2. 我无法使用Fixed(2) 处理的一个号码是changeObj.change[j][1] += value[x[0]];。如果我将其更改为 changeObj.change[j][1] = (changeObj.change[j][1] + value[x[0]]).toFixed(2); 我会收到错误 (changeObj.change[j][1] + value[x[0]]).toFixed is not a function 这会将很多数字变成疯狂的浮点数,但如果我能得到 1. 解决,我实际上可以通过测试,我只想知道它为什么会这样那个。

这是我的代码:

function checkCashRegister(price, cash, cid) {
  var cidCopy = cid.slice(0);
  cidCopy.reverse();

  const value = {
    "PENNY": 0.01,
    "NICKEL": 0.05,
    "DIME": 0.10,
    "QUARTER": 0.25,
    "ONE": 1.00,
    "FIVE": 5.00,
    "TEN": 10.00,
    "TWENTY": 20.00,
    "ONE HUNDRED": 100.00
  };

  var rawChange = cash - price;
  var remaining = rawChange;

  var changeObj = {
    status: '',
    change: []
  };

  var j = 0;

  cidCopy.forEach(x => {
    if(value[x[0]] < rawChange && remaining > 0 && remaining > value[x[0]]) {
      changeObj.change.push([x[0], 0])
      changeObj.status = "OPEN";
      while (remaining - value[x[0]] >= 0 && x[1] - value[x[0]] >= 0) {
        x[1] = (x[1] - value[x[0]]).toFixed(2);
        remaining = (remaining - value[x[0]]).toFixed(2);
        changeObj.change[j][1] += value[x[0]];
      }
      j += 1;
    }
  });

  if (remaining > 0.01) {
    changeObj.status = 'INSUFFICIENT_FUNDS';
    changeObj.change = [];
  } else if (cidCopy.every(x => {return x[1] < .01;})) {
    changeObj.status = 'CLOSED';
    changeObj.change = cid;
  } 

  console.log(changeObj);
  return changeObj;
}

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

【问题讨论】:

  • toFixed 是一个数字的方法,并产生一个字符串 - 所以,也许changeObj.change[j][1] + value[x[0]] 是一个字符串?
  • 不是字符串。我测试了console.log(typeof (changeObj.change[j][1] + value[x[0]]));,它解析为“数字”。
  • 我建议从所有计算中消除浮点数。用美分整数做所有事情。仅在需要显示(或解析)值时转换为美元和美分。
  • 好吧,changeObj.change[j][1] 是第一次通过循环的数字,但第二次它必须是一个字符串,因为.toFixed 产生一个字符串 - 您可以通过以下方式“修复”该问题changeObj.change[j][1] = (+changeObj.change[j][1] + value[x[0]]).toFixed(2); - 注意第一个(一元)+
  • 就您的“cid”复制问题而言,那是因为您传入了一个数组数组,cidcopy 与 cid 不同,但是,每个元素都指的是同一个数组,即@ 987654333@ 等 ... 另一个快速而肮脏的修复 - var cidCopy = JSON.parse(JSON.stringify(cid)) - 所以,总的来说,jsfiddle.net/k7qjmhfu 修复了这两个问题

标签: javascript arrays object ecmascript-6 floating-point


【解决方案1】:
function checkCashRegister(price, cash, cid) {
  let cashArr = cid.map(e => e[1]*100),
      converted = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000],
      rawChange = ((cash - price)*100),
      result = [["PENNY", 0],  ["NICKEL", 0],  ["DIME", 0],  ["QUARTER", 0],  ["ONE", 0],  ["FIVE", 0],  ["TEN", 0],  ["TWENTY", 0],  ["ONE HUNDRED", 0]],
      change = {status: "", change: []};
  /*This loop will do all the math at *100 to avoid rounding errors, it runs through the cashArr backwards finding
  the highest denomination of each possible change it can until the change hits 0 
  */   
  for (let i = cashArr.length - 1; i >= 0; i--) {
    while(cashArr[i] > 0) {
      if (rawChange - converted[i] >= 0) {
        result[i][1] += converted[i];
        rawChange -= converted[i];
        cashArr[i] -= converted[i];       
      } else { break; }
    }
    if (rawChange === 0) {break;}
  }
  /*This loop will go through the result Array and divide any number that's not 0 by 100 to get us back to the 
  proper format. 
  */  
  for (let i = result.length -1;i >= 0; i--){
    if (result[i][1] !== 0){
      result[i][1] = result[i][1]/100
    }
  }
  /*This if logic will check if we have zeroed the change (meaning we had enough proper change), if not, we send
  the insufficient funds message.
  */
  if (rawChange !== 0) {
    change.status = "INSUFFICIENT_FUNDS";
    return change;
  }
  /*This if logic will check if we had enough change as well as if result is the same as cid(meaning there was
  exactly enough change), if so it sends the closed message.
  */ 
  else if (rawChange === 0 && JSON.stringify(result)==JSON.stringify(cid)) {    
    change.status = "CLOSED";
    change.change = result;
    return change;        
  }
  /*Anything else will have to be we had enough change with change left over, so we send the open message after
  we reverse the results array and remove all entries that have a 0 for value. This creates the array needed for
  output.
  */ 
  else {  
    result = result.filter(e => e[1] !== 0).reverse();  
    change.status = "OPEN";
    change.change = result;
    return change;
  }
}

这是我提交的收银机测试。如果你不这样做会容易得多 尝试用小数进行数学运算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 2022-12-09
    • 2021-08-02
    • 1970-01-01
    • 2020-01-11
    • 2016-08-28
    • 1970-01-01
    相关资源
    最近更新 更多