Cash Register Project: strange number generation

Hello! I’m fairly new to the forums so I’m hoping I post this correctly… I’ve been making my way through the JavaScript certification course fairly well but this Cash Register project is killing me (around 8-10 hours put into it).

Here is the Project Link:
JavaScript Cash Register Project

Issue:
When I examine what is going on with the last test, my code is generating strange numbers… why does it suddenly jump to several decimals like that after working just fine for the previous iterations?:

0.43: this is total change left.
0.07: Amount Returned.
0.42: this is total change left.
0.08: Amount Returned.
0.41: this is total change left.
0.09: Amount Returned.
0.4: this is total change left.
0.09999999999999999: Amount Returned.
0.39: this is total change left.
0.10999999999999999: Amount Returned.
0.38: this is total change left.

My Code:

function checkCashRegister(price, cash, cid) {
//In essence, turning the cid array into an array of object that also unclude type value:
let cidObjects = [
{ cashType: ‘“ONE HUNDRED”’, amountInDrawer: cid[8][1], typeValue: 100.00 },
{ cashType: ‘“TWENTY”’, amountInDrawer: cid[7][1], typeValue: 20.00 },
{ cashType: ‘“TEN”’, amountInDrawer: cid[6][1], typeValue: 10.00 },
{ cashType: ‘“FIVE”’, amountInDrawer: cid[5][1], typeValue: 5.00 },
{ cashType: ‘“ONE”’, amountInDrawer: cid[4][1], typeValue: 1.00 },
{ cashType: ‘“QUARTER”’, amountInDrawer: cid[3][1], typeValue: .25 },
{ cashType: ‘“DIME”’, amountInDrawer: cid[2][1], typeValue: .10 },
{ cashType: ‘“NICKEL”’, amountInDrawer: cid[1][1], typeValue: .05 },
{ cashType: ‘“PENNY”’, amountInDrawer: cid[0][1], typeValue: .01 }
];

//Create a receipt object to return:
let receiptObject = {
status: “OPEN”,
change: []
};

//Test to see if not enough cash was given or exact cash:
if(price > cash){
receiptObject.status = “PAY_UP_SUCKA!!”;
return receiptObject;
} else if(price == cash){
addCashGivenToCID(cash, cidObjects);
return receiptObject;
}

//function to add received money into cash register:
function addCashGivenToCID(cash, cidObjects){
for(let i = 0; i < cidObjects.length; i++){
cidObjects[0].amountInDrawer +=
((cash / cidObjects[0].typeValue) * cidObjects[0].typeValue);
cash %= cidObjects[0].typeValue;
}
}

//Figure out what change total is needed & add money received to CID:
let changeTotal = cash - price;
addCashGivenToCID(cash, cidObjects);

//Function to calculate the various moneyTypes needed retrieve:
function subtractChangeFromCID(changeTotal, cidObjects, receiptObject){
for(let i = 0; i < cidObjects.length; i++){
let amountOfTypeReturning = 0;

  //Go through cidObjects and pull needed moneys for change to return:
  while(cidObjects[i].amountInDrawer > 0 && changeTotal >= cidObjects[i].typeValue){
    changeTotal -= cidObjects[i].typeValue;
    cidObjects[i].amountInDrawer -= cidObjects[i].typeValue;
    amountOfTypeReturning += cidObjects[i].typeValue;
    changeTotal = Math.round(changeTotal * 100) / 100;
    console.log(changeTotal + ": this is total change left.");
    console.log(amountOfTypeReturning +  ": Amount Returned.");
  }

  if(amountOfTypeReturning > 0){
    receiptObject.change.push([ cidObjects[i].cashType, amountOfTypeReturning ]);
  }
}

return receiptObject;

}

//Call function to perform calulations:
receiptObject = subtractChangeFromCID(changeTotal, cidObjects, receiptObject);

// delete below for production, just test scripts:
console.log(receiptObject);
console.log(receiptObject.change);
console.log(receiptObject.change[0][0]);
console.log(receiptObject.change[0][1]);

//Checks to see if we had the change to return:
if(receiptObject.change.length < 1 || changeTotal > 0){
receiptObject.status = ‘INSUFFICIENT_FUNDS’;
receiptObject.change = [];
return receiptObject;

//Checks to see if we had the change to return but the cid is now empty:

} else if(cidObjects.every(function(element){
if (element.amountInDrawer == 0) {
return true;
}
return false;
})){
receiptObject.status = “CLOSED”;
return receiptObject;
} else {
return receiptObject;
}
}

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]]));
// 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]]}

//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]]));
// 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]]}

//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]]}

//console.log(checkCashRegister(19.5, 20, [[“PENNY”, 0.01], [“NICKEL”, 0], [“DIME”, 0], [“QUARTER”, 0], [“ONE”, 0], [“FIVE”, 0], [“TEN”, 0], [“TWENTY”, 0], [“ONE HUNDRED”, 0]]));
//should return {status: “INSUFFICIENT_FUNDS”, change: []}

//console.log(checkCashRegister(19.5, 20, [[“PENNY”, 0.01], [“NICKEL”, 0], [“DIME”, 0], [“QUARTER”, 0], [“ONE”, 1], [“FIVE”, 0], [“TEN”, 0], [“TWENTY”, 0], [“ONE HUNDRED”, 0]]));
//should return {status: “INSUFFICIENT_FUNDS”, change: []}

Thank you for the help!

Binary floating point math is like this. In most programming languages, it is based on the IEEE 754 standard. JavaScript uses 64-bit floating point representation, which is the same as Java’s double. The crux of the problem is that numbers are represented in this format as a whole number times a power of two; rational numbers (such as 0.1, which is 1/10) whose denominator is not a power of two cannot be exactly represented.

This link might help clarify a bit further: https://floating-point-gui.de/basic/

1 Like

you will need to round your numbers to avoid the floating point problem that javascript has. (round to two decimal places)

1 Like

Wow, that article explains it very well, thank you!

After looking at hbar1st’s post, I realized I was placing the “Math.round(amountOfTypeReturning) / 100” in the wrong place to solve that issue…

hah, I just realized that I had placed that in the wrong spot when I was trouble shooting before… but that does solve the issue, thank you.