首先,您对可能原因的分析并不是这里的实际原因。
但你所说的概念叫做bias在舍入方案中。它确实存在并且是真实的 - 它只是不是您此处特定问题的原因。
在您声称造成此情况的示例中:49.5% + 50.5% = 100%,向上舍入,50% + 51% = 101%。
对于正数,向上舍入(向正无穷大舍入)相当于从零舍入。请参阅下面的舍入方案列表1 https://stackoverflow.com/questions/13542944/how-many-significant-digits-have-floats-and-doubles-in-java。
但同样,这不太可能是这里的原因,除非您碰巧得到两个相同等于 a.5 和 b.5 的相邻数字,而不是 a.7 + b.8 + c.5,或任何其他组合数字。
为了证明为什么这不是真正的原因,在这个 n 个数字的列表中,有 (n-1) 个相邻的对,如果我们做出合理的假设,即每个最后一个数字的概率相等,那么获得相邻数字的机会为 a。 5、b.5只有(0.1)^2 = 0.01
无论如何,真正的原因是由于缺少精度而引入的数值误差(由于转换为字符串“%2.1f”的数字表示被截断)(无论他们使用哪种语言,大概是 PHP、Javascript 或 Java)...
通常且最简单的解决方案是只是携带更高的精度。严格来说,这里可能只需要一位(或两位)数字,但是IEEE 754 浮点数免费为您提供 23 位尾数,因此每个人都使用它 https://stackoverflow.com/questions/13542944/how-many-significant-digits-have-floats-and-doubles-in-java.
然而,如果您确实坚持要给自己设置一个(人为的)挑战,即在精度缺失的情况下对数字进行舍入,并且在总和必须达到 100.0%(或最大化其达到 100.0% 的可能性)的约束下,有几种较少使用的舍入方案。
您可以在教科书中找到它们,但由于明显的原因,它们在现实世界中并没有太多使用,因为它们引入了随机性和可能的不确定性(尽管您可以设置随机种子,以至少确保可重复性)。
因此,无论这里的值如何,这些舍入方案(以及许多其他舍入方案,请参阅整篇文章):
[2] http://en.wikipedia.org/wiki/Rounding#Tie-writing http://en.wikipedia.org/wiki/Rounding#Tie-breaking
以下所有内容都会导致 q=.5 情况的偏差,并且您说您想完全避免使用它们(而不是携带额外的精度,这使得问题消失):
- 将一半向上舍入
- 向下圆一半
- 从零舍入一半
- 将一半向零舍入
- 将一半舍入到偶数
- 四舍五入到奇数
现在,以下是您感兴趣的内容:
如果 y 的小数部分为 0.5,则以等概率在 y + 0.5 和 y − 0.5 中随机选择 q。
优点:基本上没有整体偏见;但它在偶数和奇数 q 值中也是“公平的”。另一方面,它在结果中引入了随机成分;对相同的数据执行两次相同的计算可能会产生两个不同的结果。此外,如果人类(而不是计算机或随机设备)“随机”决定向哪个方向进行舍入,则可能会出现无意识偏见。
- 交替决胜局:
一种比大多数方法更晦涩的方法是交替进行半圆。
如果小数部分为 0.5,则向上舍入和向下舍入交替:对于第一次出现 0.5 的小数部分,向上舍入;对于第二次出现,向下舍入;等等。
如果可以有效地对 0.5 个小数部分的出现进行编号,则可以抑制结果的随机分量。但如果出现的总数为奇数,它仍然可以根据分配给第一次出现的舍入方向引入正偏差或负偏差。
如果您想阅读有关这些内容的所有内容(计算机算术以及实现它的硬件电路),一个很好的参考资料(在硬件方面很重要)是
计算机算术算法,第二版,以色列·科伦 (Israel Koren)
www.ecs.umass.edu/ece/koren/arith/
马萨诸塞大学
阿默斯特,2010