Exact Change - the fifth test

Exact Change - the fifth test
0

#1

Hello. I’ve definitely hit rounding issues. My code passes all the tests other than the fifth one. I end up with 3 cents rather than 4 cents and so ‘Insufficient Funds’ is returned. Any ideas? Thanks.

function checkCashRegister(price, cash, cid) {

  var denoms = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
  var totalInDrawer = cid.map(function(arr) {
    return arr[1];
  }).reduce(function(a, b) {
    return a + b;
  });
  var changeLeft = cash - price;
  var changeArr = [];

  if (totalInDrawer == changeLeft) {
    return "Closed";
  }

  cid.reverse();

  cid.forEach(function(arr, index) {
    if (arr[1] > 0 && changeLeft >= denoms[index]) {
      var change = Math.min(arr[1], Math.floor(changeLeft / denoms[index]) * denoms[index]);
      var forChangeArr = [];
      forChangeArr[0] = arr[0];
      forChangeArr[1] = change;
      changeArr.push(forChangeArr);
      changeLeft -= change;
      console.log(change, forChangeArr, changeLeft);
    }
  });

  if (changeLeft > 0) {
    return "Insufficient Funds";
  } else return changeArr;
}

console.log(checkCashRegister(3.26, 100.00, [
  ["PENNY", 1.01],
  ["NICKEL", 2.05],
  ["DIME", 3.10],
  ["QUARTER", 4.25],
  ["ONE", 90.00],
  ["FIVE", 55.00],
  ["TEN", 20.00],
  ["TWENTY", 60.00],
  ["ONE HUNDRED", 100.00]
]));

#2

I guess the Math.round() is causing this, because it rounds to an integer. You can avoid this by using something like this: Math.round(someValue*100)/100 to round to hundredths.

Haven’t tested it, so it might be something else.


#3

Thanks for looking. I’ve just realised I meant to use Math.floor. That gets me closer to the solution - I don’t get the $2 now. But rounding errors are now definitely causing the test to fail - I end up with 3 cents rather than 4 cents and so I get ‘Insufficient Funds’ returned. * 100 / 100 doesn’t seem to help.


#4

Change this:
changeLeft -= change;
To this:
changeLeft = Math.round((changeLeft - change)*100)/100;

Just checked and it works. (if you also change to Math.floor).

This will round the result every “turn”, so the floating point error is removed every time.


#5

Hey Ipgm,

It sounds like what you’re encountering is floating point precision in JavaScript. Sometimes when you’re working with decimals you’ll get some strange results unless you perform mathematical operation that might be between decimal numbers a certain way.

You can read more about this here: http://stackoverflow.com/questions/11695618/dealing-with-float-precision-in-javascript

You’re code is going to have to look something like this:

var difference = Math.round((parseFloat(firstNum) - parseFloat(secondNum)) * floatPrecision) / floatPrecision;

Where floatPrecision is a constant such as 1000.


#6

Brilliant. It does work. Thanks a lot. I’ll have a read about Math.round and floating points.

Time to check the answer wiki now and find out what the answer really is!


#7

Thanks for this. I’ll swot up on floating points then!