【问题标题】:How to deal with the sum of rounded percentage not being 100?如何处理四舍五入的百分比总和不是 100?
【发布时间】:2011-03-08 01:06:37
【问题描述】:

假设我们有一个带有整数的项目列表:

USA:       3 people
Australia: 2 people
Germany:   2 people

如果我们计算每个值占整个列表总和的百分比,我们会得到:

USA:       3/(3+2+2)*100 = 42.857...%
Australia: 2/(3+2+2)*100 = 28.571...%
Germany:   2/(3+2+2)*100 = 28.571...%

如果我们对它进行四舍五入,我们得到:

USA:       43%
Australia: 29%
Germany:   29%

和 43+29+29 = 101 不是 100,软件的用户看起来有点奇怪。你会如何解决这个问题?

【问题讨论】:

  • 没有真正的解决方法。这个问题也可以用另一种方式舍入。例如,11 个国家/地区,每个国家/地区都有 2 人。使用相同的数学运算,加起来只能达到 99%。如果你有 200 个国家,都只有 1 个人,那么他们都会有 0%。

标签: ruby rounding


【解决方案1】:

可以参考选举中使用的最大余数法:Wikipedia: Largest Remainder Method

在你的情况下,你有

USA:       42.857...
Australia: 28.571...
Germany:   28.571...

如果你取整数部分,你会得到

USA:       42
Australia: 28
Germany:   28

加起来是 98,你还想再拿两个。现在,你看看小数部分,它们是

USA:       0.857...
Australia: 0.571...
Germany:   0.571...

并取最大的,直到总数达到 100。如果取 USA,总数变为 99,您还想再取 1。这里问题出现了。由于您在澳大利亚和德国之间的平局为 0.571...,如果您同时参加,总数将为 101。因此您有两种方式可供选择:

(a) 如果您强烈希望总数为 100,请选择澳大利亚,不要再选择:

USA:       43
Australia: 29
Germany:   28

(b) 如果您更愿意尊重澳大利亚和德国打成平手的事实,请在这一点上停下来:

USA:       43
Australia: 28
Germany:   28

【讨论】:

  • 我刚刚实现了一个使用最大余数法的 gem,您可以在github.com/jethroo/lare_round 下查看,欢迎进一步改进;)
  • 感谢您的链接,我从未听说过,但帮助我创建了我的函数 =)
【解决方案2】:

选项 1

如果您担心结果对用户来说有点奇怪,我会在结果中添加一个脚注,其中提到百分比已四舍五入,总和可能不是 100%。仅当舍入导致此行为时,您才能以编程方式显示消息。

USA percentage:       43
Australia percentage: 29
Germany percentage:   29

*Percentages may not total 100 due to rounding

选项 2

由于您使用的是 Ruby,我建议您使用 rational 数字。这样您就不会在需要时失去精度。除了脚注之外,您还可以在旁边显示带有有理数的百分比,如下所示:

USA percentage:       43 (3/7)
Australia percentage: 29 (2/7)
Germany percentage:   29 (2/7)

选项 3

包含更多小数位,以便舍入误差不那么严重:

USA percentage:       42.9
Australia percentage: 28.6
Germany percentage:   28.6

这导致 100.1 而不是 101。

【讨论】:

  • 包含更多小数位听起来像是一个很好的解决方案/修复。
  • 添加一位小数向查看者表明这些不是整数,因此可以预期已经四舍五入。许多人在看到一个没有小数的整数时,会认为它是精确数字而不是四舍五入的数字。因此,在答案中包含一位小数是个好主意。
【解决方案3】:

由于四舍五入,组件的总和可能不等于总数。 统计报告中的标准。

秘籍会在下一个表格、报告或附录中回来咬你。您无法跟踪更改。只有不看这类报道的人才会觉得好笑。

哦,是的。它不是舍入误差。

【讨论】:

  • 我同意你的观点,只有不看这类报道的人才会觉得好笑,而且这种作弊毕竟是不必要的。不过这个作弊可能只是为了展示,内部数据会保持原样,所以不会影响下一张表等等。
【解决方案4】:

您可以通过将除最后一个以外的所有舍入结果相加并将最后一个值 100 - 前一个总和值相加来“作弊”...

在这种情况下,你会:

USA = 43
Aus = 29
Ger = 28  (100 - (43 + 29))

但这只是一个肮脏的把戏......你应该遵循马特给出的更诚实/准确的解决方案,因为我的似乎表明德国的百分比低于澳大利亚的百分比。

【讨论】:

  • 如果你打算使用肮脏的把戏,请在这样做会产生最小错误的项目上进行更正。
【解决方案5】:
    const indexes = [];
const decimalPercentages = [
  0,
  6.501707128047701,
  80.72721472499585,
  10.985525877598509,
  1.7855522693579489
];
const sum = decimalPercentages.map(d => d).reduce((a, b) => a + b, 0);
let percentages = decimalPercentages.map(d => Math.floor(d));
const percentagesTotal = percentages.reduce((a, b) => a + b, 0);

 Use the largest Remainder Method to get percentages total at 100
 inspired by https://stackoverflow.com/a/13485888/9477129
 This code implements the Largest Remainder method

if (100 - percentagesTotal) {
  const decimalValues = decimalPercentages.map((d) => {
    if (!d.toString().split('.')[1]) {
      return 0;
    }
    return d.toString().split('.')[1];
  });
  const targetIndexes = [...decimalValues].sort().splice(percentages.length -
    (100 - percentagesTotal));
  targetIndexes.forEach((element) => {
    indexes.push(decimalValues.indexOf(element));
  });
  percentages = percentages.map((element, key) => {
    if (indexes.includes(key)) {
      return element + 1;
    }
    return element;
  });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 2012-11-09
    • 2015-12-05
    • 2013-11-19
    • 1970-01-01
    • 2012-08-29
    相关资源
    最近更新 更多