民调百分比的四舍五入存在不精确性

续接 投票中百分比的四舍五入不准确 的讨论:

我决定开一个新话题,因为最新的问题并非关于有争议的舍入规则,而是完全错误的规则。因此,这个话题必须归类到 Contribute > Bug 类别。虽然不是什么大问题,但确实有些尴尬。

我们进行了一次公开投票,共有 106 票。其中 69 票投给“否”,37 票投给“是”。简单的除法计算显示,69/106 约为 65.09%。然而,系统却显示 66% 投给“否”,34% 投给“是”。请看图片:

最终结果是 72 票投给“否”,38 票投给“是”,投票现已关闭。72/110 约为 65.45%,系统也将其舍入为 66%,因此你可以在 Tappara.co 看到这一 bug 的实际表现。

我试图查看代码以找出导致 bug 的原因,但未能成功。我发现有一个名为 evenRound 的函数被调用,但当我搜索其源码时,没有找到。这只是一个猜测,也许该函数是将数字舍入到最近的 偶数 整数?

Not sure I understand what’s broken here. The poll will round the % so they add up to 100%.

1 个赞

结果很糟糕,问题就出在这里。:slight_smile:

谢谢你的代码。我只是没找到它,这说明我在用 GitHub 方面真的很菜。代码是从 Stack Overflow 上摘录的,原作者写道:

我不确定你需要多高的精度,但我建议的做法是:将小数部分总和向上取整得到的数值 n,对前 n 个数各加 1,其余的向下取整。比如这里 n 是 3,那么我就给前 3 项加 1,其余项向下取整。当然,这种方法不是超级精确,有些数字可能会在不该四舍五入的时候被舍入,但它效果还不错,而且最终结果总是 100%。

用这么粗暴的方法得到奇怪的结果也不足为奇。我建议我们要稍微复杂一点。这篇帖子 在同一个话题下获得了 72 个赞成票,而代码来源的那篇帖子只有 1 个。

如果你不介意依赖原始的小数数据,有很多方法可以做到这一点。

第一种,也许也是最流行的方法是最大余数法(Largest Remainder Method)

其基本步骤是:

  1. 将所有数字向下取整
  1. 计算总和与 100 之间的差值
  1. 按照小数部分从大到小的顺序,将差值分配给各项(每项加 1)

我认为这种方法是最好的选择。它仍然非常简单,而且结果要好得多。当前的代码需要增加几行,以便告诉函数哪些数字应该向上取整。不过,还有一个问题需要考虑。来自同一话题的 这篇帖子 指出:

Varun Vohra 的高赞答案最小化了绝对误差之和,而且实现起来非常简单。但是,它无法处理一些边缘情况——比如对 24.25、23.25、27.25、25.25 进行四舍五入时,结果应该是什么?其中有一个数字需要向上取整而不是向下取整。

该帖子提出了各种方法来选择哪些数字向上取整,哪些向下取整,但你永远无法完全避免任意性。如果你追求完美,可以进一步阅读该帖子,但在这些罕见的特殊情况下,我也满足于使用这种方法。

你大概会任意选择列表中的第一个或最后一个。

希望这能帮到你。如果我先学习一些基本语法,我的技能可能足以自己进行改进。我现在不打算这么做,但如果有人在此之前没有处理这个问题,也许以后会做。

编辑:我把标题中的“broken”改成了“imprecise”,稍微优化了一下标题。这个话题也应该移到 Contribute > Feature 频道,或者与之前的话题合并。

4 个赞

Feel free to submit a pull request to change the rounding algorithm :wink:

5 个赞

It was like classic exercises for beginning programmers. Here is a way to do it, but someone who has more experience and isn’t totally new to JavaScript might find some shortcuts.

https://github.com/rizka10/discourse/pull/1/files

2 个赞

Looks fine to me. Would you mind making it a PR so that I can merge it?

I thought that was a pull request already… I’m as confused as always with Github. :confused:
I clicked some more green buttons now, maybe it does the trick?

If you want to create a PR from your code, you should go there: https://github.com/discourse/discourse/compare/master...rizka10:master :wink:

1 个赞

I think I’m getting it now. I ran into some Github tutorials online yesterday and I should really go through one to learn the basics.

1 个赞

Awesome. Before we can merge the code, we’ll need you to sign the CLA. I promise, this is the last step (also, you only have to sign it once ;))

6 个赞

Thanks for all the help! I signed it now.

4 个赞