function checkCashRegister(price, cash, cid) { var change; var sumCid = 0; // Here is your change, ma'am. //找零(change),付款(cash),购买价格(price),收银机中零钱(cid) change = cash - price; //计算零钱总额 for (var i = 0; i < cid.length; i++) { sumCid += cid[i][1]; } return sumCid; sumCid = Number(sumCid.toFixed(2)); //保留两位小数 if (sumCid < change) { return "Insufficient Funds"; //余额不足 } else if (sumCid === change) { return "Closed"; } else { // 1.零钱不够,返回余额不足 // 2.零钱足够,找回零钱 return overChange(change, cid, sumCid); } } function overChange(change, arr, sumCid) { var array = []; var len = arr.length; for (var i = len - 1; i >= 0; i--) { if (arr[i][1] === 0) continue; if (arr[i][1] < change) { array.push(arr[i]); change -= arr[i][1]; change = Number(change.toFixed(2)); } else if (arr[i][1] > change) { var x = arr[i][0]; // 取得零钱名称 var y = 0; switch(x) { case "ONE HUNDRED": y = Math.floor(change / 100) * 100; break; case "TWENTY": y = Math.floor(change / 20) * 20; break; case "TEN": y = Math.floor(change / 10) * 10; break; case "FIVE": y = Math.floor(change / 5) * 5; break; case "ONE": y = Math.floor(change / 1); break; case "QUARTER": y = Math.floor(change / 0.25) * 0.25; break; case "DIME": y = Math.floor(change / 0.10) * 0.10; break; case "NICKEL": y = Math.floor(change / 0.05) * 0.05; break; case "PENNY": y = Math.floor(change / 0.01) * 0.01; break; } if (y === 0 && sumCid - arr[i][1] < change) { return "Insufficient Funds"; } else if (y === 0) { continue; } else { if (y < 1) { y = y; } var array1 = []; array1.push(arr[i][0]); array1.push(y); array.push(array1); change -= y; change = Number(change.toFixed(2)); } } } if (change === 0) { return array; } else { return "Insufficient Funds"; } }
题目:
设计一个收银程序 checkCashRegister()
,其把购买价格(price
)作为第一个参数 , 付款金额 (cash
)作为第二个参数, 和收银机中零钱 (cid
) 作为第三个参数.
cid
是一个二维数组,存着当前可用的找零.
当收银机中的钱不够找零时返回字符串 "Insufficient Funds"
. 如果正好则返回字符串 "Closed"
.
否则, 返回应找回的零钱列表,且由大到小存在二维数组中.
分析:
一个模拟找钱的程序。思路应该是这样的:
首先,分析函数的参数,第一个参数是商品价格price,第二参数是支付现金金额cash,第三个是柜员机当前的零钱cid,是一个二维数组,它已经将所拥有的相同面值的钱币做了一个累加,比如面值为5元的就剩35元了这样。
然后我们来分析函数的实现逻辑,结账时,会先扫描一下商品的价格,做一个累加,得到总的支付金额比如说78元,然后你给的钱是现金的话是不是要给50+20+5+1*3或者10*7+1*8等等等的组合。
//找零(change),付款(cash),购买价格(price),收银机中零钱(cid) change = cash - price;
但是你刚好没有零钱,最小100,你只能给100。那么此时基于交易等价交换的原则,柜员机得找零对吧,而且得找得回这么多零钱对吧,找不回就返回字符串"Insufficient Funds",表示零钱不足,交易基于等价交换的原则无法进行。那么你要先求找零的金额大小,然后与柜员机当前的零钱总额作比较。找零的金额为 cash - price,当前柜员机的零钱总额为各个面值大小的纸币的金额总额相加。数组是规律的,第一项是钱币面值,第二项是该面值的钱币总额。所以可以循环遍历叠加金额。
//计算零钱总额 for (var i = 0; i < cid.length; i++) { sumCid += cid[i][1]; }
当可以找零的时候,你会拿钱,而且是一个面值的纸币一个面值的纸币的拿吧,不会找27元你找个27个一元钱吧。最简便的做法总是先给一张较大的但小于当前需要找零的零钱的纸币。这是使用循环变量递减的原因。
for (var i = len - 1; i >= 0; i--) {
你没找零多少钱需要找得零钱总额在减小
change -= y;
还有一种情况就是,有可能柜员机零钱总额足够找零,但是找不开,比如说要找零3元,但你最小的纸币只剩下5元了,这时也是需要返回字符串"Insufficient Funds",表示零钱不足,交易基于等价交换的原则无法进行。
if (y === 0 && sumCid - arr[i][1] < change) { return "Insufficient Funds"; }
if (change === 0) { return array; } else { return "Insufficient Funds"; }
change == 0 是判断能否成功找零的直接标准。
如果循环结束了,change != 0,说明现在的零钱找不开。否则返回需要找回的零钱。
方法参考文档
Number.prototype.toFixed()
toFixed()
方法使用定点表示法来格式化一个数。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed