证明福勒的货币分配算法是正确的

时间:2009-11-05 09:13:35

标签: algorithm currency allocation proof

Martin Fowler has a Money class有一个货币分配程序。该例程根据给定的比率列表分配资金,而不会通过舍入而损失任何价值。它会将任何余数值传播到结果上。

例如,按“比率”(1,1,1)分配的100美元将产生(34美元,33美元,33美元)。

以下是allocate功能:

public long[] allocate(long amount, long[] ratios) {
    long total = 0;
    for (int i = 0; i < ratios.length; i++) total += ratios[i];

    long remainder = amount;
    long[] results = new long[ratios.length];
    for (int i = 0; i < results.length; i++) {
        results[i] = amount * ratios[i] / total;
        remainder -= results[i];
    }

    for (int i = 0; i < remainder; i++) {
        results[i]++;
    }

    return results;
}

(为了这个问题,为了使它更简单,我冒昧用long取代Money类型。)

问题是,我怎么知道它是正确的?除了最终的for-loop之外,这一切似乎都是不言而喻的。我认为为了证明函数是正确的,在最终的for循环中证明以下关系是正确的就足够了:

remainder < results.length

有人可以证明吗?

4 个答案:

答案 0 :(得分:23)

关键的洞察力是,在计算每个result[i]时,总余数等于各个余数的总和。

由于每个单独的余数是四舍五入的结果,因此最多为1.剩余results.length个余数,因此总余数最多为results.length

编辑:显然,这不是一个没有漂亮符号的证明,所以这里有一些...
alt text

答案 1 :(得分:1)

无需证明。

基本金额通过简单划分,四舍五入。 因此,分配的金额将始终小于或等于总金额。

剩余包含未分配的金额。哪个总是比'i'少一整数。所以他只是给每个接收器1,直到钱不见了。

答案 2 :(得分:1)

简单

只使用

这个事实

α=地板(A / B)* B +(A%B)

答案 3 :(得分:0)

我会说这不正确,因为一些奇怪的比例可能导致余数大于结果数。因此,我建议results[i % results.length].amount++;

编辑:我撤回了我的回答。有多头没有好奇的比例,浮点模数没有帮助