我正在寻找一种算法来将金额拆分为单项附加值。 解释这个的最简单方法是展示一个例子。 让我们想象一下8.13及以下项目的数量
Item Qty Price Item totals
---------------------------------------------------------------------------
1 2 1.00 2.00
2 3 2.00 6.00
3 11 3.00 33.00
Total: 41.00
Expected total: 41.00 + 8.13 = 49.13
我发现每个项目最接近的额外数量是8.13:
Item Qty Price Add-on amount Final Price Item totals
---------------------------------------------------------------------------
1 2 1.00 0.52 1.52 3.04
2 3 2.00 0.53 2.53 7.59
3 11 3.00 0.50 3.50 38.50
Total: 49.13
有没有解决这个问题的算法?项目数量可能有所不同,有时数量可能会重复,等等。
更新1
如其中一条评论所述,我想避免四舍五入。在这种情况下,我意识到会有一些情况会给我带来一些不可能在没有舍入的情况下均匀分配的数量,即
Item Qty Price Item totals Add-on amount
---------------------------------------------------------------------------
1 5 1.00 5.00 0.01
2 5 2.00 10.00 0.01
3 5 3.00 15.00 0.01
Total: 30.00 Rest: 0.02
Expected total: 30.00 + 0.17 = 30.17
在我的原始示例中,当我计算附加金额时,我没有考虑价格,因为我的主要目标是均匀地分配金额,而不一定按比例分配。但是,如果有一个解决方案可以按比例分配数量来解决这个问题,我将非常乐意使用它。
答案 0 :(得分:0)
让我们定义您拥有的参数:
Q i =商品数量 i
P i =商品的价格 i
T = total = Σ i = 1..n (Q i ×P i )< / em>的
TA =总附加量
TQ =总数量= Σ i = 1..n (Q i )
A i =商品 i 的附加金额(待定)
然后你可以分两步完成。首先确定每个A i 的下限以及之后剩余的附加组件:
AL = A i的下限 (对于所有 i ,因为我们的目标是均匀分布项目)
R =需要以某种方式分发的TA的剩余部分
可以按如下方式计算:
AL =⌊TA/TQ⌋,被截断为分
寸 R = TA - AL×TQ
对于您的示例数据,其工作原理如下:
AL =⌊8.13/(2 + 3 + 11)⌋= 0.50
R = 8.13 - 0.50×(2 + 3 + 11)= 0.13
然后,您将按数量的降序浏览项目列表,因此首先是最大数量:
E =⌊R/ Q i ⌋,向下舍入到分号 A i = AL + E
R = R - E×Q i
如果您要为数量最小的项目再加1分,您可以选择检查 R 是否具有较小的绝对值。
这不会给出最佳解决方案,如果最佳意味着 R 必须最接近于零0不同的 A i 的。但是为了获得这样的结果,必须进行进一步的除数分析,这种分数并不总是在线性时间内完成,并且可能导致极值,其中一个项目可以覆盖整个附加值,而所有其他项目将得到0.00添加 - 上。
回到示例案例:它将按如下方式运行:
E =⌊0.13/11⌋ = 0.01 A 3 = 0.50 + 0.01 = 0.51
R = 0.13 - 0.01×11 = 0.02E =⌊0.02/3⌋ = 0.00 A 2 = 0.50 + 0.00 = 0.50
R = 0.02 - 0.00×3 = 0.02E =⌊0.02/2⌋ = 0.01 A 1 = 0.50 + 0.01 = 0.51
R = 0.02 - 0.01×2 = 0.00
+-----+------------+--------+-------+-------------------+
| Qty | Unit Price | Add-on | Price | Price with add-on |
+-----+------------+--------+-------+-------------------+
| 2 | 1.00 | 0.51 | 2.00 | 3.02 |
| 3 | 2.00 | 0.50 | 6.00 | 7.50 |
| 11 | 3.00 | 0.51 | 33.00 | 38.61 |
+-----+------------+--------+-------+-------------------+
| | Add-on:| 8.13 | |
| 15 | | 49.13 | 49.13 |
+-----+ +-------+-------------------+
+-----+------------+--------+-------+-------------------+
| Qty | Unit Price | Add-on | Price | Price with add-on |
+-----+------------+--------+-------+-------------------+
| 5 | 1.00 | ? | 5.00 | ? |
| 5 | 2.00 | ? | 10.00 | ? |
| 5 | 3.00 | ? | 15.00 | ? |
+-----+------------+--------+-------+-------------------+
| | Add-on:| 0.17 | |
| 15 | | 30.17 | ? |
+-----+ +-------+-------------------+
算法将设置:
AL =⌊0.17/(5 + 5 + 5)⌋= 0.01
R = 0.17-0.01×(5 + 5 + 5)= 0.02
...并且循环不会改变任何东西,因为2美分小于最小量:
+-----+------------+--------+-------+-------------------+
| Qty | Unit Price | Add-on | Price | Price with add-on |
+-----+------------+--------+-------+-------------------+
| 5 | 1.00 | 0.01 | 5.00 | 5.05 |
| 5 | 2.00 | 0.01 | 10.00 | 10.05 |
| 5 | 3.00 | 0.01 | 15.00 | 15.05 |
+-----+------------+--------+-------+-------------------+
| | Add-on:| 0.17 | |
| 16 | | 30.17 | 30.15 (R = 0.02)|
+-----+ +-------+-------------------+
答案 1 :(得分:0)
让我们以美分来衡量所有价格,以便只涉及整数。
然后问题变成如下:
给出几个正整数 a 1 ,..., n (数量)和整数 S (要添加的数量),找到非负整数 p 1 ,...,p n (要添加的价格)所以 a 1 p 1 + ... + a n p n = S
正如您已经注意到的,这个问题并不总是有解决方案。有两个问题:
a 1 = 4, 2 = 6,S = 13
这是一个无解决方案的例子,因为 a 1 和 a 2 都可以被<整除em> 2 ,而 S 不是。
a 1 = 4, 2 = 7,S = 13
这仍然是一个无解的例子,尽管有整数解(例如4 * 5 + 7 *( - 1)= 13)。
如果没有指定如何处理无解决方案,则无法使用完整的算法。但在这里,我想提供extended euclidean algorithm的链接,这完全解决了案例 n = 2 ,并且肯定是最终解决方案的关键工具。