//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() 的临时解决方法。
最佳答案
您完全走在正确的道路上。但是,不是每次都在内循环中调用 push
,而是需要添加循环时上次推送的数量。可能最简单的方法是添加一个变量,然后在最后推送。您还必须检查 cashInDrawer
并在添加到“total”时减少 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);
}
关于javascript - 如何在 Javascript 中将一个数组值递增到另一个数组值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53681042/