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



在这种情况下,我需要计算一系列数字余额的百分比,四舍五入到小数点后10位,但它们的总和必须为1.000000000(或1.0000000000%(。我可以得到0.9999999998或1.000000004,但我似乎无法得到1.0。我还能做什么吗?

create table balances (balance number); 
insert into balances (balance) select 27544020.38 from dual; 
insert into balances (balance) select 3161670.46 from dual; 
insert into balances (balance) select 13085937.87 from dual; 
insert into balances (balance) select 0 from dual; 
insert into balances (balance) select 0 from dual; 
insert into balances (balance) select 478033.04 from dual; 
insert into balances (balance) select -85126.17 from dual; 
insert into balances (balance) select 44968439.88 from dual; 
insert into balances (balance) select 78155926.33 from dual; 
insert into balances (balance) select -3662788.36 from dual; 
insert into balances (balance) select 234328177.96 from dual; 
insert into balances (balance) select 103694040.23 from dual; 
insert into balances (balance) select 85295156.11 from dual; 
insert into balances (balance) select 155627180.9 from dual; 
insert into balances (balance) select 133311464.77 from dual; 
insert into balances (balance) select 56306616.42 from dual; 
insert into balances (balance) select 135204546.73 from dual; 
insert into balances (balance) select 188572856.42 from dual; 
insert into balances (balance) select 118208964.69 from dual; 
insert into balances (balance) select 87751901.55 from dual; 
insert into balances (balance) select 947 from dual; 
insert into balances (balance) select 61190729.16 from dual; 
insert into balances (balance) select 35307571.39 from dual; 
insert into balances (balance) select 32229181.69 from dual; 
insert into balances (balance) select 27544020.38 from dual; 
insert into balances (balance) select 3161670.46 from dual; 
insert into balances (balance) select 13085937.87 from dual; 

我用计算这组余额的百分比

ratio_to_report(balance) over ()

并用将其四舍五入到小数点后10位

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

当我运行类似的查询时

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

这个结果看起来不错,但当我通过检查总和(pctg(时

select sum(pctg) from 
(
select balance, 
ratio_to_report(balance) over (),
round(ratio_to_report(balance) over (), 10) pctg
from balances
)

我得到:

SUM(PCTG) 
------------------ 
1.0000000004

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

没有完美的方法来解决这个问题。从本质上讲,四舍五入确实会影响全局计算,之后你所能做的一切都只是围绕基本的数学规则。

脑海中浮现的一项肮脏的工作是计算四舍五入值的运行总和,并仅计算其中一个值,以便总数匹配;例如,我们可以获得最大的pctg(因为它可能不那么引人注目(。这是不干净的,在边缘情况下可能会产生反直觉的结果,甚至是错误的结果。

这看起来像:

select  
rtr,
pctg,
case when row_number() over(order by pctg desc) = 1
then 1 - sum(pctg) over(order by pctg) - pctg
else pctg
end adujsted_ptcg
from (
select 
balance, 
ratio_to_report(balance) over () rtr,
round(ratio_to_report(balance) over (), 10) pctg
from balances
) t
order by pctg desc

当然,还有其他选择(比如计算总体不匹配,然后尝试在行组中或多或少地平均分配(,但无论如何,这些选择都不是干净的。

这里有一种方法-它是"最佳";在某种意义上(它是"最优"的特定意义是不平凡的,也许不是特别相关(。

with
prep (balance, rn, p_sum) as (
select balance, rownum, 
sum(balance) over (order by rownum) / sum(balance) over ()
from   balances
)
select balance, 
round(p_sum, 10) - round(lag(p_sum, 1, 0) over (order by rn), 10)
as percentage
from   prep
;

其想法是跟踪百分比的非四舍五入累计总和;然后对这些累积总和进行四舍五入;然后取连续四舍五入的累积和的差作为"差";四舍五入值";百分比。

";最佳方式"-只是不要要求数学证明:如果你考虑";"四舍五入";百分比,每个非四舍五入的百分比最多小数点后十位,限制条件是总和必须恰好等于1,然后计算"的平方和;错误";(这个有趣的四舍五入百分比减去确切的百分比(,我在这个查询中实现的策略将最小化这个误差平方和。

这也可以用ratio_to_report来写,但由于我不能在同一查询中对其进行分析求和,所以我更喜欢计算";报告比率;直接地

如果我没有错的话,这个问题是由除法破坏的值引起的。示例:三行,每行值为10。每一行代表总数的1000/3%或33.‾3%。例如33.3+33.3+33.3=99.9,而33。

因此,你不能将单个百分比四舍五入到n位数,但仍然可以保证总数为100。你要么自愿伪造一些数字,要么展示分数。

相关内容

  • 没有找到相关文章