# Cash Register Confusion: I'm a penny short?!

I have come up with a solution (albeit longwinded) but it is ALMOST correct. I am one cent short of the answer for the test argument I’m checking. It should be [“PENNY”, 0.04] but in my finalArr array I get [“PENNY”, 0.03]

I’m assuming there is a rounding error occurring somewhere in my code. Am I on the right track?

I have included comments before each step/section to help explain my thought process.
Any constructive feedback is welcome!

``````
function checkCashRegister(price, cash, cid) {
var change = cash - price;
console.log('change =', change)

// sum all cash in drawer
var cidSum = 0;
for (var i = 0; i < cid.length; i++) {
cidSum += cid[i][1];
}
// WHY DOES IT PRODUCE A REPEATING DECIMAL???
// console.log(cidSum)
// round to the nearest hundredth
cidSum = Math.round(100*cidSum)/100;
// console.log('cidSum =', cidSum)

// array of unit values
var unit = [0.01, 0.05, 0.1, 0.25, 1, 5, 10, 20, 100];

// array of how many units each are available in drawer
var numOfUnit = [];
for (var i = 0; i < cid.length; i++) {
numOfUnit.push(Math.round(cid[i][1]/unit[i]))
}
// console.log(numOfUnit)

// start at hundred unit + loop backwards
// substract unit value from change total
// decrement the number of currency units available
// push values into changeDue array
var changeDue = [];
for (var i = unit.length - 1; i >= 0; i--) {
while (change > unit[i] && numOfUnit[i] > 0) {
change -= unit[i];
//console.log(change)
numOfUnit[i]--;
//console.log(numOfUnit)
changeDue.push(unit[i]);
}
}
// console.log('changeDue:', changeDue)
// console.log(change)

// create empty 2D array to add currency values
var returnArr =
[["ONE HUNDRED", 0],
["TWENTY", 0],
["TEN", 0],
["FIVE", 0],
["ONE", 0],
["QUARTER", 0],
["DIME", 0],
["NICKEL", 0],
["PENNY", 0]];

// add values to empty array for each unit of currency
for (var i = 0; i < changeDue.length; i++) {
if (changeDue[i] == 100) {
returnArr[0][1] += 100;
} else if (changeDue[i] == 20) {
returnArr[1][1] += 20;
} else if (changeDue[i] == 10) {
returnArr[2][1] += 10;
} else if (changeDue[i] == 5) {
returnArr[3][1] += 5;
} else if (changeDue[i] == 1) {
returnArr[4][1] += 1;
} else if (changeDue[i] == 0.25) {
returnArr[5][1] += 0.25;
} else if (changeDue[i] == 0.1) {
returnArr[6][1] += 0.1;
} else if (changeDue[i] == 0.05) {
returnArr[7][1] += 0.05;
} else if (changeDue[i] == 0.01) {
returnArr[8][1] += 0.01;
}
}

// include unit of currency only if value > 0
var finalArr = []
for (var i = 0; i < unit.length; i++) {
if (returnArr[i][1] > 0){
finalArr.push(returnArr[i])
}
}
console.log(finalArr)

// sum values from finalArr to get exactChange total
var exactChange = 0;
for (var i = 0; i < finalArr.length; i++) {
exactChange += finalArr[i][1];
}
console.log('exactChange =', exactChange)

// 1. Is there enough change/can u make exact change?
if (cidSum < change || change != exactChange) {
return {status: "INSUFFICIENT_FUNDS", change: []};
}

// 2. Is cash in drawer sum == change due?
if (cidSum == change) {
return {status: "CLOSED", change: [cid]};
}

// 3. Return array with change in decreasing value
return {status: "OPEN", change: finalArr};
}

console.log(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]]}
``````
``````   **Your browser information:**
``````

User Agent is: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36`.

Challenge: Cash Register

I have not read all of your code yet, but I know some general things that can occur with this specific challenge is that if the values become floats they can go from being say `2.08` to being `2.0799999999999999` (infinite nines) now obviously a true infinitely repeating number cannot be made, and this will skew your values.

``````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]]));
//{ status: 'INSUFFICIENT_FUNDS', change: [] }
//should have been
//{status: "CLOSED", change: [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]}
//If you take a look at how many pennies you have left however
//[ 'PENNY', 0.49000000000000027 ]
``````

You need to force the values to round correctly, this will help: Number.prototype.toFixed() - JavaScript | MDN
`toFixed` returns a string so you will need to make sure to change it back to a number

1 Like

Yes and no. As you have noticed after adding all cash in drawer `cidSum` ends up almost what it should. Operations on float numbers can be imprecise, this is caused by the way they are internally represented (if you find this interesting I’d suggest search for this topic for more specifics). I’d suggest to try to figure out way that would make all (or almost all) operations to be performed on integers.

1 Like

So I tried using toFixed() and parseFloat().

``````// sum all cash in drawer
var cidSum = 0;
for (var i = 0; i < cid.length; i++) {
cidSum += Number.parseFloat(cid[i][1]).toFixed(2)
console.log(cidSum)
}
``````

But it just concats the floats as strings. Shouldn’t parseFloat convert the fixed decimal string back to a number??
01.01
01.012.05
01.012.053.10
01.012.053.104.25
01.012.053.104.2590.00
01.012.053.104.2590.0055.00
01.012.053.104.2590.0055.0020.00
01.012.053.104.2590.0055.0020.0060.00
01.012.053.104.2590.0055.0020.0060.00100.00

you are calling `toFixed` on the number created by `parseFloat` so `parseFloat` is happening first then `toFixed` happens

``````console.log(Number.parseFloat(1.222).toFixed(2)) //'1.22'
``````

This would work `Number(cid[i][1].toFixed(2))`

1 Like

I just tried putting parentheses around (cid[i][1]).toFixed(2)
So that fixes the concatenation issue, but why arent all the values forced to round correctly?

``````// sum all cash in drawer
var cidSum = 0;
for (var i = 0; i < cid.length; i++) {
cidSum += Number.parseFloat((cid[i][1]).toFixed(2))
console.log(cidSum)
``````
``````1.01
3.0599999999999996
6.16
10.41
100.41
155.41
175.41
235.41
335.40999999999997
``````

Okay I just did:

``````var cidSum = 0;
for (var i = 0; i < cid.length; i++) {
cidSum += Number(cid[i][1].toFixed(2))
console.log(cidSum)
}

Output:
1.01
3.0599999999999996
6.16
10.41
100.41
155.41
175.41
235.41
335.40999999999997
``````

Not sure what is happening.

Make sure you are using `Number(cid[i][1].toFixed(2))` when are doing something can cause floats, such as division

1 Like

Remember `+=` operator there is an equivalent of writing it:

``````cidSum = cidSum + Number(cid[i][1].toFixed(2))
``````

This will still have the same precision issues.

1 Like

Okay I will make sure to do that, but why is it still producing a repeating decimal when I am using `Number(cid[i][1].toFixed(2))`?

``````var cidSum = 0;
for (var i = 0; i < cid.length; i++) {
cidSum += Number(cid[i][1].toFixed(2))
console.log(cidSum)
}

Output:
1.01
3.0599999999999996
6.16
10.41
100.41
155.41
175.41
235.41
335.40999999999997
``````

Why is this not producing a fixed rounded value for each execution of the loop? I’m just finding a sum, not performing division, correct?

can you put down all of your current code

1 Like

Okay its pretty much the same as before. It’s kinda long.

``````function checkCashRegister(price, cash, cid) {
var change = cash - price;
console.log('change =', change)

// sum all cash in drawer
var cidSum = 0;
for (var i = 0; i < cid.length; i++) {
cidSum += Number(cid[i][1].toFixed(2))
//console.log(cidSum)
}
// WHY DOES IT PRODUCE A REPEATING DECIMAL???
//console.log(cidSum)
// round to the nearest hundredth
cidSum =  Math.round(100*cidSum)/100;
//console.log('cidSum =', cidSum)

// array of unit values
var unit = [0.01, 0.05, 0.1, 0.25, 1, 5, 10, 20, 100];

// array of how many units each are available in drawer
var numOfUnit = [];
for (var i = 0; i < cid.length; i++) {
numOfUnit.push(Math.round(cid[i][1]/unit[i]))
}
console.log(numOfUnit)

// start at hundred unit + loop backwards
// substract unit value from change total
// decrement the number of currency units available
// push values into changeDue array
var changeDue = [];
for (var i = unit.length - 1; i >= 0; i--) {
while (change > unit[i] && numOfUnit[i] > 0) {
change -= unit[i];
//console.log(change)
numOfUnit[i]--;
//console.log(numOfUnit)
changeDue.push(unit[i]);
}
}
// console.log('changeDue:', changeDue)
// console.log(change)

// create empty 2D array to add currency values
var returnArr =
[["ONE HUNDRED", 0],
["TWENTY", 0],
["TEN", 0],
["FIVE", 0],
["ONE", 0],
["QUARTER", 0],
["DIME", 0],
["NICKEL", 0],
["PENNY", 0]];

// add values to empty array for each unit of currency
for (var i = 0; i < changeDue.length; i++) {
if (changeDue[i] == 100) {
returnArr[0][1] += 100;
} else if (changeDue[i] == 20) {
returnArr[1][1] += 20;
} else if (changeDue[i] == 10) {
returnArr[2][1] += 10;
} else if (changeDue[i] == 5) {
returnArr[3][1] += 5;
} else if (changeDue[i] == 1) {
returnArr[4][1] += 1;
} else if (changeDue[i] == 0.25) {
returnArr[5][1] += 0.25;
} else if (changeDue[i] == 0.1) {
returnArr[6][1] += 0.1;
} else if (changeDue[i] == 0.05) {
returnArr[7][1] += 0.05;
} else if (changeDue[i] == 0.01) {
returnArr[8][1] += 0.01;
}
}

// include unit of currency only if value > 0
var finalArr = []
for (var i = 0; i < unit.length; i++) {
if (returnArr[i][1] > 0){
finalArr.push(returnArr[i])
}
}
console.log(finalArr)

// sum values from finalArr to get exactChange total
var exactChange = 0;
for (var i = 0; i < finalArr.length; i++) {
exactChange += finalArr[i][1];
}
console.log('exactChange =', exactChange)

// 1. Is there enough change/can u make exact change?
if (cidSum < change || change != exactChange) {
return {status: "INSUFFICIENT_FUNDS", change: []};
}

// 2. Is cash in drawer sum == change due?
if (cidSum == change) {
return {status: "CLOSED", change: [cid]};
}

// 3. Return array with change in decreasing value
return {status: "OPEN", change: finalArr};
}

console.log(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]]}
``````

I’m refactoring your code, but its taking a little bit, but if you use `toFixed` in the loop where you create `cidSum` you can then check if `cidSum === change` and if thats true you can `return` the `closed` condition which will pass you one more test

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.