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

假设一个订单购买了 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 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 43
jcc123

把误差放在其中一个sku中

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

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

3年前 评论
xiaobei (楼主) 3年前
deatil (作者) 3年前
xiaobei (楼主) 3年前
xiaobei (楼主) 3年前
deatil (作者) 3年前
xiaobei (楼主) 3年前
deatil (作者) 3年前
xiaobei (楼主) 3年前

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

3年前 评论
颠倒的玉石

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

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

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

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

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

3年前 评论

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

3年前 评论

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

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

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

3年前 评论
chowjiawei 3年前
xiaobei (楼主) 3年前
<?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;
    }
}
3年前 评论
Dcatplus-杨光

假设一个订单购买了 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

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

3年前 评论
xiaobei (楼主) 3年前
Dcatplus-杨光 (作者) 3年前
xiaobei (楼主) 3年前

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

3年前 评论

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

3年前 评论

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

2年前 评论
阿凡 2年前

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