Algorithm 如何使四舍五入的百分比总和达到100%

Algorithm 如何使四舍五入的百分比总和达到100%,algorithm,math,rounding,percentage,Algorithm,Math,Rounding,Percentage,考虑以下四个百分比,表示为float数字: 13.626332% 47.989636% 9.596008% 28.788024% ----------- 100.000000% 我需要将这些百分比表示为整数。如果我简单地使用Math.round(),我最终得到的总数是101% 14 + 48 + 10 + 29 = 101 如果我使用parseInt(),我最终得到了97% 13 + 47 + 9 + 28 = 97 在保持总数为100%的情况

考虑以下四个百分比,表示为
float
数字:

    13.626332%
    47.989636%
     9.596008%
    28.788024%
   -----------
   100.000000%
我需要将这些百分比表示为整数。如果我简单地使用
Math.round()
,我最终得到的总数是101%

14 + 48 + 10 + 29 = 101
如果我使用
parseInt()
,我最终得到了97%

13 + 47 + 9 + 28 = 97
在保持总数为100%的情况下,将任何百分比数表示为整数的好算法是什么


编辑:在阅读了一些评论和答案后,显然有很多方法可以解决这个问题

在我看来,为了保持数字的真实性,“正确”的结果是使总体误差最小化的结果,其定义是相对于实际值的误差舍入程度:

        value  rounded     error               decision
   ----------------------------------------------------
    13.626332       14      2.7%          round up (14)
    47.989636       48      0.0%          round up (48)
     9.596008       10      4.0%    don't round up  (9)
    28.788024       29      2.7%          round up (29)
在平局(3.33、3.33、3.33)的情况下,可以做出任意决定(例如3、4、3)。

可能做到这一点的“最佳”方法(引用“最佳”是一个主观术语)是保持你所在位置的连续(非整数)记录,并对该值进行四舍五入

然后将其与历史一起使用,以确定应该使用什么值。例如,使用您提供的值:

Value      CumulValue  CumulRounded  PrevBaseline  Need
---------  ----------  ------------  ------------  ----
                                  0
13.626332   13.626332            14             0    14 ( 14 -  0)
47.989636   61.615968            62            14    48 ( 62 - 14)
 9.596008   71.211976            71            62     9 ( 71 - 62)
28.788024  100.000000           100            71    29 (100 - 71)
                                                    ---
                                                    100
在每个阶段,您都不会对数字本身进行四舍五入。取而代之的是,对累积值进行四舍五入,并计算出从上一个基线达到该值的最佳整数-该基线是上一行的累积值(四舍五入)

这是因为您不会在每个阶段丢失信息,而是更智能地使用信息。“正确”的四舍五入值在最后一列中,您可以看到它们的总和为100

在上面的第三个值中,您可以看到这与盲目舍入每个值之间的差异。虽然
9.596008
通常会四舍五入到
10
,但累计的
71.211976
正确地四舍五入到
71
——这意味着只需
9
就可以添加到
62
之前的基线中


这也适用于“有问题”的序列,如三个大致的-
1/3
值,其中一个值应向上舍入:

Value      CumulValue  CumulRounded  PrevBaseline  Need
---------  ----------  ------------  ------------  ----
                                  0
33.333333   33.333333            33             0    33 ( 33 -  0)
33.333333   66.666666            67            33    34 ( 67 - 33)
33.333333   99.999999           100            67    33 (100 - 67)
                                                    ---
                                                    100

如果你把它四舍五入,没有好的方法可以使它在所有情况下都完全相同

您可以取N个百分比的小数部分(在您给出的示例中为4)

添加小数部分。在您的示例中,分数部分的总和=3

Ceil是分数最高的3个数字,floor是其余的


(抱歉编辑)

您可以尝试跟踪由于舍入而产生的错误,如果累计错误大于当前数字的小数部分,则可以根据粒度进行舍入

13.62 -> 14 (+.38)
47.98 -> 48 (+.02 (+.40 total))
 9.59 -> 10 (+.41 (+.81 total))
28.78 -> 28 (round down because .81 > .78)
------------
        100
不确定这在一般情况下是否有效,但如果顺序颠倒,其效果似乎相似:

28.78 -> 29 (+.22)
 9.59 ->  9 (-.37; rounded down because .59 > .22)
47.98 -> 48 (-.35)
13.62 -> 14 (+.03)
------------
        100

我敢肯定,在某些边缘情况下,这可能会出现问题,但任何方法都至少会有些随意,因为您基本上是在修改输入数据。

不要对舍入的数字求和。你会得到不准确的结果。根据术语的数量和分数部分的分布,总数可能会显著减少

显示四舍五入的数字,但对实际值求和。根据您呈现数字的方式,实际的方式会有所不同。这样你就可以

14 48 10 29 __ 100 不管你走哪条路,你都会有分歧。在您的示例中,如果不以错误的方式“舍入”一个值,则无法显示总计为100的数字(最小的错误是将9.596更改为9)

编辑

您需要在以下选项中进行选择:

  • 项目的准确性
  • 总和的准确性(如果对四舍五入值求和)
  • 四舍五入项目与四舍五入总和之间的一致性)
  • 大多数情况下,在处理百分比时#3是最好的选择,因为当总数等于101%时,比单个项目总数不等于100时更明显,并且您可以保持单个项目的准确性。“四舍五入”9.596到9在我看来是不准确的


    为了解释这一点,我有时会添加一个脚注,解释单个值是四舍五入的,可能不是100%——任何理解四舍五入的人都应该能够理解这一解释。

    有很多方法可以做到这一点,只要你不担心依赖原始的十进制数据

    第一种,也许也是最流行的方法是

    基本上是:

  • 把每件事都凑齐
  • 求和与100之差
  • 通过按项目小数部分降序向项目添加1来分配差额
  • 在您的情况下,它将是这样的:

    13.626332%
    47.989636%
     9.596008%
    28.788024%
    
    如果取整数部分,则得到

    13
    47
     9
    28
    
    加起来是97,你还想再加三个。现在,你看小数部分,它们是

    .626332%
    .989636%
    .596008%
    .788024%
    
    取最大的,直到总数达到100。所以你会得到:

    14
    48
     9
    29
    

    或者,您可以简单地选择显示一位小数而不是整数值。因此,数字将是48.3和23.9等。这将使方差从100大幅下降。

    这是银行家四舍五入的情况,也称为“四舍五入-一半-偶数”。它由BigDecimal支持。它的目的是确保四舍五入平衡,即不利于银行或客户。

    我不确定您需要的准确度,但我要做的只是将第一个
    n
    数字加上1,
    n
    是小数总数的ceil。在本例中,这是
    3
    ,因此我将在前3项中添加1,并删除其余项。当然,这不是超精确的,有些数字可能会在不应该的时候向上或向下取整,但它工作正常,并且总是会得到100%

    所以
    [13.626332,47.989636,9.596008,28.788024]
    将是
    [14,48,10,28]
    ,因为
    Math.ceil(.626332+.989636+.596008+.788024)==3

    功能均衡(arr){
    变量
    
    14
    48
     9
    29
    
      13.626332
      47.989636
       9.596008
    + 28.788024
    -----------
     100.000000
    
     Original      Rounded   Absolute error
       13.626           13          0.62633
        47.99           48          0.01036
        9.596           10          0.40399
     + 28.788           29          0.21198
    ---------------------------------------
      100.000          100          1.25266
    
     Original      Rounded   Absolute error
       13.626           14          0.37367
        47.99           48          0.01036
        9.596            9          0.59601
     + 28.788           29          0.21198
    ---------------------------------------
      100.000          100          1.19202
    
    -------------------------------------------------
    | original  | question | % diff | mine | % diff |
    -------------------------------------------------
    | 13.626332 | 14       | 2.74%  | 13   | 4.5%   |
    | 47.989636 | 48       | 0.02%  | 48   | 0.02%  |
    | 9.596008  | 9        | 6.2%   | 10   | 4.2%   |
    | 28.788024 | 29       | 0.7%   | 29   | 0.7%   |
    -------------------------------------------------
    | Totals    | 100      | 9.66%  | 100  | 9.43%  |
    -------------------------------------------------
    
    DAY 1
    who |  real | app
    ----|-------|------
      A | 33.34 |  34
      B | 33.33 |  33
      C | 33.33 |  33
    
    DAY 2
    who |  real | app
    ----|-------|------
      A | 33.35 |  33
      B | 33.36 |  34
      C | 33.29 |  33