Cash Register, float calculations errors

Cash Register, float calculations errors
0.0 0

#1

Hi there, I could really use some help on the cash register. I’ve been stuck for hours, and I feel like I’m close to figuring it out, but I can’t seem to wrap my finger around the issue.

The problem has to do with float calculations, they’re inaccurate and I think they’re giving me a rounding error especially on the pennies. I seem to be off on 0.01 on the following tests:

checkCashRegister(3.26, 100, [[“PENNY”, 1.01], [“NICKEL”, 2.05], [“DIME”, 3.1], [“QUARTER”, 4.25], [“ONE”, 90], [“FIVE”, 55], [“TEN”, 20], [“TWENTY”, 60], [“ONE HUNDRED”, 100]]) should return {status: “OPEN”, change: [[“TWENTY”, 60], [“TEN”, 20], [“FIVE”, 15], [“ONE”, 1], [“QUARTER”, 0.5], [“DIME”, 0.2], [“PENNY”, 0.04]]}.

When I check my calculations, penny turns out to be 0.03.

checkCashRegister(19.5, 20, [[“PENNY”, 0.5], [“NICKEL”, 0], [“DIME”, 0], [“QUARTER”, 0], [“ONE”, 0], [“FIVE”, 0], [“TEN”, 0], [“TWENTY”, 0], [“ONE HUNDRED”, 0]]) should return {status: “CLOSED”, change: [[“PENNY”, 0.5], [“NICKEL”, 0], [“DIME”, 0], [“QUARTER”, 0], [“ONE”, 0], [“FIVE”, 0], [“TEN”, 0], [“TWENTY”, 0], [“ONE HUNDRED”, 0]]}.

Here, my penny ends up with 0.49.

Here’s my code so far:

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

function checkCashRegister(price, cash, cid) {
  let change = cash - price;
  // calculate total cash in drawer
  let cidTotal = 0;
  
  for (let i = 0; i<cid.length; i++) {
    cidTotal += cid[i][1];
  }

  const cidCopy = cid.slice();
   // make sure to only round at 2 decimals
   cidTotal = Math.round(cidTotal * 100) / 100;
  // if total cash in drawer is less then change, return.
  if (change > cidTotal) {
    return {status: "INSUFFICIENT_FUNDS", change: []}
  }
  // create arr to push change on
  let changeArr = [];
  // loop over cid backwards, so we start with the highest amount. 
  for(let j = cid.length - 1; j >= 0; j--){
    // reduce change with current money in cid 
    let nameOfValue = cid[j][0];
    let valueAmount = 0;
        while (change > 0 && cid[j][1] > 0) {
          if ( change < 0 || cid[j][1] < 0) {
            break;
          } else if ((change - REGOBJ[nameOfValue]) < 0) {
            break;
          }
          
          change -= REGOBJ[nameOfValue];
          cid[j][1] -= REGOBJ[nameOfValue];
          valueAmount += REGOBJ[nameOfValue];
          cidTotal -= REGOBJ[nameOfValue];      
    } // end of while loop
    if (valueAmount > 0) {
      valueAmount = Math.round(valueAmount * 100) / 100;
    changeArr.push(nameOfValue, valueAmount);
    }

  } // end of for loop
console.log(changeArr);
  // if change is still over 0 after the loop we dont have exact change
  if (change > 0) {
    return {status: "INSUFFICIENT_FUNDS", change: []};
    // if total equals 0, we have exact change 
  } else if (cidTotal === 0) {
    return  {status: "CLOSED", change: [cidCopy]}
  } else {
  return{status: "OPEN", change: [changeArr]};
  }
}

checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);


#2

Consider treating cents as your base unit (1 cent = 1, 1 dollar = 100). That way, you won’t need to deal with the messiness of floating-point arithmetic. Of course, you’ll need to convert back before returning anything.