将四舍五入的小数百分比相加为1(或100%)

a11xaf1n  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(1551)

我有一个要求,在这种情况下,计算一系列数字余额的百分比,四舍五入到小数点后10位,但它们必须合计为1.0000000000(或100.0000000000%)。我可以得到0.9999998或1.0000000004,但我似乎不能得到1.0。还有什么我能做的吗?

  1. create table balances (balance number);
  2. insert into balances (balance) select 27544020.38 from dual;
  3. insert into balances (balance) select 3161670.46 from dual;
  4. insert into balances (balance) select 13085937.87 from dual;
  5. insert into balances (balance) select 0 from dual;
  6. insert into balances (balance) select 0 from dual;
  7. insert into balances (balance) select 478033.04 from dual;
  8. insert into balances (balance) select -85126.17 from dual;
  9. insert into balances (balance) select 44968439.88 from dual;
  10. insert into balances (balance) select 78155926.33 from dual;
  11. insert into balances (balance) select -3662788.36 from dual;
  12. insert into balances (balance) select 234328177.96 from dual;
  13. insert into balances (balance) select 103694040.23 from dual;
  14. insert into balances (balance) select 85295156.11 from dual;
  15. insert into balances (balance) select 155627180.9 from dual;
  16. insert into balances (balance) select 133311464.77 from dual;
  17. insert into balances (balance) select 56306616.42 from dual;
  18. insert into balances (balance) select 135204546.73 from dual;
  19. insert into balances (balance) select 188572856.42 from dual;
  20. insert into balances (balance) select 118208964.69 from dual;
  21. insert into balances (balance) select 87751901.55 from dual;
  22. insert into balances (balance) select 947 from dual;
  23. insert into balances (balance) select 61190729.16 from dual;
  24. insert into balances (balance) select 35307571.39 from dual;
  25. insert into balances (balance) select 32229181.69 from dual;
  26. insert into balances (balance) select 27544020.38 from dual;
  27. insert into balances (balance) select 3161670.46 from dual;
  28. insert into balances (balance) select 13085937.87 from dual;

我用以下公式计算这组余额的百分比:

  1. ratio_to_report(balance) over ()

四舍五入到小数点后10位:

  1. round(ratio_to_report(balance) over (), 10)

当我运行如下查询时:

  1. select balance, ratio_to_report(balance) over (), round(ratio_to_report(balance) over (), 10) as pctg
  2. from balances;

这个结果看起来不错,但是当我通过以下方式检查总和(pctg)时:

  1. select sum(pctg) from
  2. (
  3. select balance,
  4. ratio_to_report(balance) over (),
  5. round(ratio_to_report(balance) over (), 10) pctg
  6. from balances
  7. )

我得到:

  1. SUM(PCTG)
  2. ------------------
  3. 1.0000000004

在将小数百分比四舍五入到10位小数时,是否有其他技术或函数可以始终得到1.0000000000的和?

i7uaboj4

i7uaboj41#

没有完美的方法可以解决这个问题。从本质上讲,舍入这些值确实会影响全局计算,而之后所能做的任何事情都只是围绕基本的数学规则进行。
我想到的一个棘手的工作是计算四舍五入值的连续和,并调整其中一个值以使总数匹配;例如,我们可以选择最棒的 pctg (因为它可能不那么明显)。这是不干净的,在边缘的情况下,可能会产生反直觉的-甚至错误的-结果。
这看起来像:

  1. select
  2. rtr,
  3. pctg,
  4. case when row_number() over(order by pctg desc) = 1
  5. then 1 - sum(pctg) over(order by pctg) - pctg
  6. else pctg
  7. end adujsted_ptcg
  8. from (
  9. select
  10. balance,
  11. ratio_to_report(balance) over () rtr,
  12. round(ratio_to_report(balance) over (), 10) pctg
  13. from balances
  14. ) t
  15. order by pctg desc

当然,还有其他的替代方法(比如计算整体的不匹配,然后尝试在多个行组之间或多或少地平均分配它),但是它们中没有一个是干净的。

展开查看全部
pieyvz9o

pieyvz9o2#

这里有一种方法——在某种意义上它是“最优的”(在特定意义上它是“最优的”是不平凡的,也许不是特别相关)。

  1. with
  2. prep (balance, rn, p_sum) as (
  3. select balance, rownum,
  4. sum(balance) over (order by rownum) / sum(balance) over ()
  5. from balances
  6. )
  7. select balance,
  8. round(p_sum, 10) - round(lag(p_sum, 1, 0) over (order by rn), 10)
  9. as percentage
  10. from prep
  11. ;

其思想是跟踪百分比的非四舍五入累积和;然后对这些累积和进行四舍五入;然后取连续四舍五入累计和之差作为百分比的“四舍五入值”。
“最佳方法”-只是不要求数学证明:如果你考虑所有的“四舍五入”百分比分配,每个非四舍五入百分比最多10位小数,限制条件是总和必须正好等于1,然后你计算“错误”的平方和(这个有趣的四舍五入百分比减去确切的百分比),我在这个查询中实现的策略将最小化这个误差平方和。
这也可以用 ratio_to_report ,但由于我不能在同一个查询中对其进行分析求和,所以我更喜欢直接计算“与报表的比率”。

展开查看全部
ebdffaop

ebdffaop3#

如果我没弄错的话,这个问题是由于价值观被分割而产生的。例如:三行,每行值为10。每行代表总数的1000/3%或33.3%(对不起,我还没有找到一种方法来把这三个连翘取出来,如果你把它四舍五入到任何数字上,你得到的总和就会比原来的总和小。e、 g.33.3+33.3+33.3=99.9,33.‾3+33.‾3+33.‾3=100。
因此,您不能将单个百分比四舍五入到n位数,而仍然可以得到100个保证值。你要么自愿伪造一些数字,要么显示分数。

相关问题