PHP买赠优惠脚本问题:免费商品数量计算错误排查
解决「买N赠M」优惠活动中免费商品数量计算错误的问题
问题背景
需开发PHP脚本支持管理员配置「购买N件指定商品,获赠M件指定商品」的优惠,计算总商品中的免费商品数量,覆盖以下优惠类型:
- 买1赠1
- 买1赠2
- 买2赠1
- 买4赠3
现有测试代码通过修改顶部$buy和$get变量调整规则,但遇到问题:当购物车总数量为2(如p1=1、p2=1)时,预期免费商品数为1,但实际计算结果为0。
现有代码
$buy = 1; $get = 2; $free= 0; $sum = $buy + $get; for($qty=1;$qty<=100;$qty++) { if($buy >= $get){ $free= (int) round(($qty/$sum), PHP_ROUND_HALF_DOWN); }else if($buy < $get){ $free= (int) round(($qty/$sum), PHP_ROUND_HALF_UP); } $free*= $get; echo "Result = Qty = ".$qty." Free = ".($free)."\n"; }
问题分析
现有代码的核心错误是使用四舍五入计算优惠组数,不符合「买N赠M」的实际逻辑:
- 四舍五入规则无法匹配优惠的阶梯性要求,比如当
$buy=2、$get=1时,总数量2除以sum=3得到0.666,用HALF_DOWN舍去为0,导致免费数为0,这符合买2赠1的规则(需凑够3件才能得1件免费),但如果是买1赠1的规则,这种逻辑就会出错。 - 代码未限制免费数量不能超过总商品数,比如当
$buy=1、$get=2时,总数量2会算出免费数2,显然不合理(总数量才2,不可能全是免费)。
正确解决方案
正确逻辑是:根据「每购买$buy件付费商品,可获得$get件免费商品」的规则,计算最大免费数量,同时满足付费数量 = 总数量 - 免费数量,且付费数量需足够支撑对应的免费数量。
通过数学推导得出免费数量最大值:
$$free = \lfloor \frac{qty \times get}{buy + get} \rfloor$$
同时增加验证,避免极端情况导致付费数量不足。修正后的代码:
$buy = 1; $get = 1; $sum = $buy + $get; for($qty=1;$qty<=100;$qty++) { // 计算最大可能的免费数量 $free = (int) floor(($qty * $get) / $sum); // 验证付费数量是否足够支撑免费数量 $paid = $qty - $free; while ($paid < ceil($free / $get) * $buy && $free > 0) { $free--; $paid = $qty - $free; } echo "Result = Qty = ".$qty." Free = ".($free)."\n"; }
验证示例
- 当规则为买1赠1(
$buy=1、$get=1),总数量2时:
$$free = floor((2*1)/(1+1)) = 1$$
符合预期结果。 - 当规则为买2赠1(
$buy=2、$get=1),总数量3时:
$$free = floor((3*1)/(2+1)) = 1$$
符合优惠逻辑。 - 当规则为买1赠2(
$buy=1、$get=2),总数量2时:
$$free = floor((2*2)/(1+2)) = 1$$
付费数量1满足买1件的要求,免费1件符合合理预期。
内容的提问来源于stack exchange,提问作者Pirogrammer
相关产品推荐
相关产品推荐

