这是一个人为的问题,但对我们的行业来说是一个真实的问题。
我们客户租用的酒店房间,出于酒店会计的原因,房费每晚都计入账本,而不是一次全部计入。我一直在努力修复我们的统一费率计算模块,该模块已完全损坏。
问题的一个例子是 - 客户同意为 30 晚住宿支付 376 美元。但是,376 美元不是 1 次记入账簿,而是(376 美元/晚)为每晚住宿记在账簿上。
因此,给定整个住宿所需的总计、住宿天数和税率 - 我们如何获得小计列表,当征税和汇总时,它将等于总计。我们现有的解决方案是要求酒店员工手动调整,这容易出错且繁重。我们希望价格尽可能均匀分布,以使会计报告尽可能准确。
现在有点乱,我无法用正确的晚数获得总计。我觉得应该有一个算法来解决这个问题,我只是不知道。
我目前正在研究的涉及这个尾递归函数,
function iterationRate($amount, $days, $tax, $ary=array()){
$amount_left = $amount;
// we have subtotals already, subtract these from the desired total
if(count($ary) > 0) {
$amount_left = bcsub($amount, sumWithTaxes($ary, $tax));
}
// make sure it's a valid currency amount
$amount_left = bcround($amount_left, 2);
$tonights_rate = bcdiv($amount_left/$tax, $days);
// prevent negative charges / credit
if ($tonights_rate >= 0) {
array_push($ary, bcround($tonights_rate, 2));
}
else {
// remove an item from the array to give us more space
array_shift($ary);
$days = $days + 1;
}
if($days > 1) {
return iterationRate($amount, $days - 1, $tax, $ary);
}
$test_subtotals = sumWithTaxes($ary, $tax);
$diff = bcsub($test_subtotals, $amount);
// if we don't have our amount, remove the diff from an item and try again
if(abs($diff) > 0) {
$firstnight = array_shift($ary);
array_push($ary, bcsub($firstnight, $diff));
return iterationRate($amount, $days, $tax, $ary);
}
return $ary;
}
整个测试在这里:http ://sandbox.onlinephpfunctions.com/code/9eb43e95fad866ef7198a0e2bfa778edf326e091
例子
3晚300美元,税率16.25%
从总数中查找小计并除以夜数将不起作用:300/(1 + 税率) = $258.0645,四舍五入为 $258.06 $258.06 / 3 = 86.02
86.02 * 税率 = 99.9983,四舍五入为 99.99。99.99 * 3 != 300。
有效的小计数组,[86.02, 86.02, 86.04] 2 * (86.02 * taxrate ) + (86.04 * taxrate) = total