Oh man, this is a lot to explain. So I was working on the final algorithm in the javascript section, the cash register. I got to a point where the math was doing weird things it definitely shouldn’t be doing. So I read up on how Javascript is dumb when it comes to completing operations with decimals. I read about that here:
http://adripofjavascript.com/blog/drips/avoiding-problems-with-decimal-math-in-javascript.html
Basically the advice in this article, if working with money anyway, is to multiply things by 100 before doing calculations, and then divide them by 100 in the end. You’re converting the values into whole numbers, doing the operations needed, and then dividing by 100 to make them back into money format (with two decimal places). So I was annoyed I’d have to rewrite a bunch of code, but at least I knew how to fix it.
That is, until I realized that doesn’t always work… So I come to a point in my code where I’m trying to count out quarters for change (I’ve put in comments to hopefully make it easy to find this, but it’s line 78), and I need to turn the number 16.74 into a whole number. But multiplying by 100 doesn’t work. It returns some giant decimal (1673.99999999998) instead of 1674 like it should. I don’t know what to do. Can you help?
Here is the link to the challenge I’m working on:
Cash Register
And here is my code. It’s probably overly long and complicated, and I’m not done. I’m sure the fcc solution is much more elegant, but I think I can figure out all the other things. It’s just this incorrect math stuff I need help with. If I can get javascript to do math correctly, I can totally finish writing this algorithm on my own.
function checkCashRegister(price, cash, cid) {
//Where price is the total the customer must pay, cash is the cash they pay with, and cid defines the amount of money in the drawer.
let cashBack = cash - price;
let dollars = Math.floor(cashBack);
let drawer = cid;
let hundredsDrawer = drawer[8][1];
let twentiesDrawer = drawer[7][1];
let tensDrawer = drawer[6][1];
let fivesDrawer = drawer[5][1];
let onesDrawer = drawer[4][1];
let quartersDrawer = drawer[3][1];
let dimesDrawer = drawer[2][1];
let nickelsDrawer = drawer[1][1];
let penniesDrawer = drawer[0][1];
let change = []
let result = {
status: "OPEN",
change: []
};
//Generate the correct amount of change to give the customer, or else return "Insufficient funds. "
while (cashBack > 0) {
//ONE HUNDRED:
if (dollars >= 100 && hundredsDrawer >= 100) {
let hundredsNeeded = Math.floor(dollars / 100) * 100;
if (hundredsDrawer >= hundredsNeeded) {
change.push(['ONE HUNDRED', hundredsNeeded]);
dollars -= hundredsNeeded;
hundredsDrawer -= hundredsNeeded;
cashBack = ((cashBack * 100) - (hundredsNeeded * 100)) /100;
} else {
change.push(['ONE HUNDRED', hundredsNeeded]);
dollars -= hundredsDrawer;
hundredsDrawer = 0;
cashBack = ((cashBack * 100) - (hundredsDrawer * 100)) /100;
}
//TWENTY:
} else if (dollars >= 20 && twentiesDrawer >= 20) {
let twentiesNeeded = Math.floor(dollars / 20) * 20;
if (twentiesDrawer >= twentiesNeeded) {
change.push(['TWENTY', twentiesNeeded]);
dollars -= twentiesNeeded;
cashBack = ((cashBack * 100) - (twentiesNeeded * 100)) /100;
twentiesDrawer -= twentiesNeeded;
} else {
change.push(['TWENTY', twentiesDrawer]);
dollars -= twentiesDrawer;
cashBack = ((cashBack * 100) - (twentiesDrawer * 100)) /100;
twentiesDrawer = 0;
}
//TEN:
} else if (dollars >= 10 && tensDrawer >= 10) {
let tensNeeded = Math.floor(dollars / 10) * 10;
if (tensDrawer >= tensNeeded) {
change.push(['TEN', tensNeeded]);
dollars -= tensNeeded;
cashBack = ((cashBack * 100) - (tensNeeded * 100)) /100;
tensDrawer -= tensNeeded;
} else {
change.push(['TEN', tensDrawer]);
dollars -= tensDrawer;
cashBack = ((cashBack * 100) - (tensDrawer * 100)) /100;
tensDrawer = 0;
}
console.log(cashBack);
//FIVE:
} else if (dollars >= 5 && fivesDrawer >= 5) {
let fivesNeeded = Math.floor(dollars / 5) * 5;
if (fivesDrawer >= fivesNeeded) {
change.push(['TEN', fivesNeeded]);
dollars -= fivesNeeded;
//
//
//
//The line below this is where the problem is. With the current arguments passed into the function (the ones I console logged out below), cashBack is currently 16.74. But when 16.74 gets multiplied by 100 in the line below, it returns NOT 1674, but rather 1673.99999999998. So once that happens, none of the rest of the math works.
//
//
//
cashBack = ((cashBack * 100) - (fivesNeeded * 100)) /100;
} else {
change.push(['FIVE', fivesDrawer]);
dollars -= fivesDrawer;
cashBack = ((cashBack * 100) - (fivesDrawer * 100)) /100;
fivesDrawer = 0;
}
//ONE:
} else if (dollars >= 1 && onesDrawer >= 1) {
let onesNeeded = dollars;
if (onesDrawer >= onesNeeded) {
change.push(['ONE', onesNeeded]);
dollars = 0;
cashBack = ((cashBack * 100) - (onesNeeded * 100)) /100;
onesDrawer -= onesNeeded;
} else {
change.push(['ONE', onesDrawer]);
dollars -= onesDrawer;
cashBack = ((cashBack * 100) - (onesDrawer * 100)) /100;
onesDrawer = 0;
}
//QUARTER:
} else if (cashBack >= 0.25 && quartersDrawer >= 0.25) {
//Escape js division problems by working with whole numbers.
let quartersNeeded = (cashBack * 100) / 25; //This is a whole number, representing the number of quarters needed, not their value.
if (quartersDrawer >= quartersNeeded * 0.25) {
change.push(['QUARTER', quartersNeeded * 0.25]);
//
//
//You'll need to fix the line below probably.
//
//
cashBack = ((cashBack * 100) - (quartersNeeded * 0.25)) / 100;
quartersDrawer -= (quartersNeeded * 0.25);
} else {
change.push(['QUARTER', quartersDrawer]);
//
//
//You'll need to fix the line below probably.
//
//
cashBack = (cashBack * 100 - quartersDrawer) / 100;
quartersDrawer = 0;
}
//DIME:
} else if (cashBack >= 0.10 && dimesDrawer >= 0.10) {
//Escape js division problems with whole numbers.
let dimesNeeded = (cashBack * 100) / 10;
if (dimesDrawer >= dimesNeeded * 0.10) {
change.push(['DIME', dimesNeeded * 0.10]);
//
//
//You'll need to fix the line below probably.
//
//
cashBack = ((cashBack * 100) - (quartersNeeded * 0.10)) / 100;
dimesDrawer -= (dimesNeeded * 0.10);
} else {
change.push(['DIME', dimesDrawer]);
//
//
//You'll need to fix the line below probably.
//
//
cashBack = (cashBack * 100 - dimesDrawer) / 100;
dimesDrawer = 0;
}
//NICKEL:
} else if (cashBack >= 0.05 && nickelsDrawer >= 0.05) {
//Escape js division problems with whole numbers.
let nickelsNeeded = (cashBack * 100) / 5;
if (nickelsDrawer >= nickelsNeeded * 0.05) {
change.push(['NICKEL', nickelsNeeded * 0.05]);
//
//
//You'll need to fix the line below probably.
//
//
cashBack = ((cashBack * 100) - (quartersNeeded * 0.05)) / 100;
nickelsDrawer -= (nickelsNeeded * 0.05);
} else {
change.push(['NICKEL', nickelsDrawer]);
//
//
//You'll need to fix the line below probably.
//
//
cashBack = (cashBack * 100 - nickelsDrawer) / 100;
nickelsDrawer = 0;
}
} else if (penniesDrawer >= cashBack) {
let penniesNeeded = cashBack;
change.push(['PENNY', cashBack]);
cashBack = 0;
drawer[0][1] = drawer[0][1] - cashBack;
} else {
cashBack = 0; //You put this to fix the endless loop. You might not keep this?
//Something that returns the INSUFFICIENT_FUNDS thing.
}
}
//May an if statement to adjust the status to "closed" if you are out of funds.
//Erase what's below this, and instead return the result object with the status and the change for the customer.
return change;
}
console.log(
// 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]]),
// '\n',
'\n',
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]])
);