//value of currency denominations
var currencyTable = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
//total cash at each currencyTable denomination in the cash register
var cashInDrawer = [100, 60, 20, 55, 90, 4.25, 3.1, 2.05, 1.01];
//total change due
var changeDue = 96.74;
我的目标是将可用的现金从最大的现金面额向最低的现金正确地找回。
当 changeDue > = 时,我不知道如何将 currencyTable 中的值增加到 cashInDrawer 中的可用金额。 > currencyTable [i] 。
到目前为止,我已经做到了:
var total = [];
for (let i = 0; i < currencyTable.length; i++){
while (changeDue >= currencyTable[i]){
total.push(currencyTable[i])
changeDue-=currencyTable[i];
}
}return total;
但这只会返回:
[20, 20, 20, 20, 10, 5, 1, 0.25, 0.25, 0.1, 0.1, 0.01, 0.01, 0.01]
我要返回的地方:
[60, 20, 15, 1, 0.5, 0.2, 0.04]
在循环中的某个地方,我意识到将changeDue更改为重复的小数,但我发现了使用 .toFixed()的临时解决方法。
答案 0 :(得分:2)
您完全在正确的道路上。但是,您不必在内部循环中每次都调用push
,而需要添加到上一次循环时所推送的数量。可能最简单的方法是添加一个变量,然后在末尾推送。添加到“总计”时,您还必须检查cashInDrawer
并减少cashInDrawer
。
这有一个固有的问题:您正在使用JavaScript的数字类型处理钱。但是JavaScript的数字类型不适合处理金钱,IEEE-754二进制浮点值在十进制领域中有臭名昭著的不精确问题,例如著名的:
console.log(0.1 + 0.2); // 0.30000000000000004
这就是这个问题。如果我们仅应用上述逻辑修正,就可以得到(见***
行):
//value of currency denominations
var currencyTable = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
//total cash at each currencyTable denomination in the cash register
var cashInDrawer = [100, 60, 20, 55, 90, 4.25, 3.1, 2.05, 1.01];
//total change due
var changeDue = 96.74;
var total = [];
for (let i = 0; i < currencyTable.length; i++){
let amount = 0; // ***
while (changeDue >= currencyTable[i] && cashInDrawer[i] > 0) { // ***
amount += currencyTable[i]; // ***
changeDue -= currencyTable[i];
cashInDrawer[i] -= currencyTable[i]; // ***
}
// I assume you want to push the amount even if it's 0
total.push(amount); // ***
}
//return total;
console.log(total);
请注意,最后一项是0.03
,而不是0.04
。这是因为changeDue
越来越不精确,我们可以查看是否将其记录下来:
//value of currency denominations
var currencyTable = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
//total cash at each currencyTable denomination in the cash register
var cashInDrawer = [100, 60, 20, 55, 90, 4.25, 3.1, 2.05, 1.01];
//total change due
var changeDue = 96.74;
var total = [];
for (let i = 0; i < currencyTable.length; i++){
let amount = 0; // ***
while (changeDue >= currencyTable[i] && cashInDrawer[i] > 0) { // ***
amount += currencyTable[i]; // ***
changeDue -= currencyTable[i];
cashInDrawer[i] -= currencyTable[i]; // ***
console.log(changeDue);
}
// I assume you want to push the amount even if it's 0
total.push(amount); // ***
}
//return total;
console.log(total);
最后,0.009999999999994869
不是>=
0.1
,因此循环提早结束。
有关解决此问题的各种方法,请参见this question's answers。
一种常见的解决方案是使用数字* 100
并保持舍入。 (有时您可以使用* 10000
,然后四舍五入到小数点后两位,依此类推。)这是一般性的想法,请根据需要进行调整:
//value of currency denominations
var currencyTable = [100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
currencyTable = currencyTable.map(entry => Math.round(entry * 100)); // ***
//total cash at each currencyTable denomination in the cash register
var cashInDrawer = [100, 60, 20, 55, 90, 4.25, 3.1, 2.05, 1.01];
cashInDrawer = cashInDrawer.map(entry => Math.round(entry * 100)); // ***
//total change due
var changeDue = 96.74;
changeDue = Math.round(changeDue * 100); // ***
var total = [];
for (let i = 0; i < currencyTable.length; i++){
let amount = 0;
while (changeDue >= currencyTable[i] && cashInDrawer[i] > 0) {
amount += currencyTable[i];
changeDue -= currencyTable[i];
cashInDrawer[i] -= currencyTable[i];
}
// I assume you want to push the amount even if it's 0
total.push(amount);
}
//return total;
for (const entry of total) {
console.log(entry / 100);
}
答案 1 :(得分:-1)
您需要汇总货币项目的数量。尝试关注
var total = [];
for (let i = 0; i < currencyTable.length; i++){
var cCount = 0;
while (changeDue >= currencyTable[i]){
cCount++;
changeDue-=currencyTable[i];
}
total.push(cCount*currencyTable[i])
}
return total;