代码之家  ›  专栏  ›  技术社区  ›  dan-gph

证明Fowler的资金分配算法是正确的

  •  15
  • dan-gph  · 技术社区  · 16 年前

    马丁福勒 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替换了货币类型。)

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

    remainder < results.length
    

    有人能证明吗?

    4 回复  |  直到 12 年前
        1
  •  24
  •   stevemegson    16 年前

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

    results.length 这样的余数,所以总余数最多是 结果.长度 .

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

        2
  •  1
  •   James Anderson    16 年前

    不需要证据。

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

    余数包含未分配的金额。它总是一个小于“i”的整数。因此,他只需给每个接收者1,直到钱用完为止。

        3
  •  1
  •   Luka Rahne    16 年前

    简单的

    a=楼层(a/b)*b+(a%b)

        4
  •  0
  •   DaClown    16 年前

    results[i % results.length].amount++; .

    编辑:我收回我的答案。对于long,没有奇怪的比率,而对于浮点模则没有帮助

    推荐文章