求教订单优惠金额均摊问题

假设一个订单购买了 2 个sku
sku1 单价为 5,数量为 3
sku2 单价为 8,数量为 5
订单总金额为 55,优惠了 20,实付 35
求每个 sku 实际均摊单价是多少?(ps: 需考虑除不尽的问题)

有误差版本:
sku1 实际均摊单价 = 5/55 * 20 = 1.82 (四舍五入取两位)
sku2 实际均摊单价 = 8/55 * 20 = 2.91 (四舍五入取两位)

1.82 * 3 + 2.91 * 5 = 20.01 ,但是实际是优惠了 20,这里算出来误差多出 0.01

求教各位大佬,如何消除这个误差

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 43
jcc123

把误差放在其中一个sku中

1.82 + (20-20.01) = 1.81
2年前 评论
xiaobei (楼主) 2年前
jcc123 (作者) 2年前
xiaobei (楼主) 2年前
lufeijun1234 2年前
ycstar 2年前

最后一个用总额减前面的总和

2年前 评论
xiaobei (楼主) 2年前
deatil (作者) 2年前
xiaobei (楼主) 2年前
xiaobei (楼主) 2年前
deatil (作者) 2年前
xiaobei (楼主) 2年前
deatil (作者) 2年前
xiaobei (楼主) 2年前
陈先生

误差放到最后一个计算的sku中 @jcc123 说的对 计算的时候尽量使用bcmath 可以尽可能的避免你说的这个问题

2年前 评论
颠倒的玉石

肯定是总数减最后一个,我一般是平均金额保留两位,其余的都舍掉,不走5入(少了可以加,多了还真没地方减),这样总金额肯定是小于等于总优惠数。然后把差价加到最后一件商品上

2年前 评论
xiaobei (楼主) 2年前
颠倒的玉石 (作者) 2年前
xiaobei (楼主) 2年前

我也遇到过,把缺少的或者增加的,补到一个sku中;特别是测试 测的支付0.01 元 通过优惠扣减,下了 123件商品,平摊不了吧,这个应该和你遇到一样的问题了

2年前 评论
xiaobei (楼主) 2年前
liaosp (作者) 2年前
xiaobei (楼主) 2年前
liaosp (作者) 2年前
xiaobei (楼主) 2年前

假如订单总额是 53分 均摊到 3个一样的 sku 上。 多出来 53%3 = 2 分。 先平均分每一个占 17,再把多出来的两分给前两个 sku 上。 也就是 18,18,17 这样均摊了。

2年前 评论

之前做过这样的需求,订单优惠金额是要按照每个商品占订单总价的比例单独进行计算并存入数据库的。

2年前 评论

没有最优解,我们以前也遇到了,即使放在最后一个商品上,可也能不对,比如最后计算出多出1,放最后一个sku,但是最后一个sku数量是3,依然除不尽,还要考虑单价是否小于折扣

2年前 评论
xiaobei (楼主) 2年前
Imuyu (作者) 2年前

请教一下,把优惠金额均摊到每一个sku上面的意义是什么,是由于多店铺的原因吗?

2年前 评论
chowjiawei 2年前
xiaobei (楼主) 2年前
<?php

/**
 * WeEngine Document System
 *
 * (c) We7Team 2019 <https://www.w7.cc>
 *
 * This is not a free software
 * Using it under the license terms
 * visited https://www.w7.cc for more details
 */

namespace W7\Sdk\Order\Base\Distributor;

use Webmozart\Assert\Assert;

/**
 * 按比例分摊优惠
 * Class ProportionalIntegerDistributor
 * @package W7\Sdk\Order\Model\Service\Distributor
 */
final class ProportionalIntegerDistributor
{
    /**
     * 分摊优惠
     * @param array|int[] $integers
     * @param int $amount
     * @return array
     */
    public function distribute(array $integers, int $amount): array
    {
        Assert::allInteger($integers);

        $total = array_sum($integers);
        $distributedAmounts = [];

        foreach ($integers as $element) {
            $distributedAmounts[] = (int)round(($element * $amount) / $total, 0, \PHP_ROUND_HALF_DOWN);
        }

        $missingAmount = $amount - array_sum($distributedAmounts);
        for ($i = 0, $iMax = abs($missingAmount); $i < $iMax; ++$i) {
            $distributedAmounts[$i] += $missingAmount >= 0 ? 1 : -1;
        }

        return $distributedAmounts;
    }
}
2年前 评论

假设一个订单购买了 2 个 sku
sku1 单价为 5,数量为 3
sku2 单价为 8,数量为 5
订单总金额为 55,优惠了 20,实付 35

其它的方法

sku1 总金额 53 = 15 优惠比例金额 (55/15) *20 = 5.4的优惠。
sku2 总金额 8
5 = 40 优惠比例金额 (55/40) 20 = 14.6的优惠。
*
均摊到每个数量**
sku1 = 5.4 / 3 = 1.8
sku2 = 14.6 / 5 = 2.92
最后就是除不尽的问题
比方说:
sku2 = 14.6 / 3 = 4.866666666667
能不能过一个函数均摊,变成 4.86,4.87,4.87

不知道我的思路是不是对。

2年前 评论
xiaobei (楼主) 2年前
YeRic (作者) 2年前
xiaobei (楼主) 2年前

那要看你们产品上是怎么定义的呀,首先肯定是到 分。 其次就是均摊的时候是舍弃还是向上向下取。 最后一个商品用总额减就行了

2年前 评论

不要钻牛角尖 这个仅仅只是用来展示 你这个实际的优惠还是总额减

2年前 评论

这个问题解决了没 我也遇到这个问题了 单价会除不尽

1年前 评论
阿凡 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!