首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将四舍五入的小数百分比添加到等于1(或100%)

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

Stack Overflow用户
提问于 2020-08-01 04:48:50
回答 3查看 382关注 0票数 1

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

代码语言:javascript
复制
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; 

我正在计算这组余额的百分比:

代码语言:javascript
复制
ratio_to_report(balance) over ()

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

代码语言:javascript
复制
round(ratio_to_report(balance) over (), 10) 

当我运行如下查询时:

代码语言:javascript
复制
select balance, ratio_to_report(balance) over (), round(ratio_to_report(balance) over (), 10) as pctg
from balances;

这个结果看起来不错,但是当我通过以下命令检查sum(pctg)时:

代码语言:javascript
复制
select sum(pctg) from 
(
   select balance, 
          ratio_to_report(balance) over (),
          round(ratio_to_report(balance) over (), 10) pctg
   from balances
)

我得到了:

代码语言:javascript
复制
      SUM(PCTG) 
------------------ 
   1.0000000004

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

EN

回答 3

Stack Overflow用户

发布于 2020-08-01 05:13:05

没有完美的方法来解决这个问题。从本质上讲,四舍五入的值确实会影响全局计算,之后可以做的任何事情都只是绕过基本的数学规则。

脑海中浮现的繁琐工作之一是计算四舍五入值的连续和,并调整其中一个值以使总值匹配;例如,我们可以调整最大的pctg (因为它可能不太明显)。这是不干净的,在边缘情况下可能会产生与直觉相反的结果,甚至是错误的结果。

这看起来像是:

代码语言:javascript
复制
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

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

票数 2
EN

Stack Overflow用户

发布于 2020-08-01 10:01:02

这里有一种方法-它在某种意义上是“最优的”(在特定的意义上,它是“最优的”,并且可能不是特别相关)。

代码语言:javascript
复制
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编写,但由于我不能在同一查询中对其进行分析求和,因此我更喜欢直接计算“报告比率”。

票数 2
EN

Stack Overflow用户

发布于 2020-08-01 05:26:05

如果我没记错的话,问题产生于价值被分割。例如:三行,每行的值为10。每一行代表总数的1000/3 %或33.‾3%。(很抱歉,我还没有找到一种方法来获得three上的纽带,它应该在那里。)如果将其四舍五入到任意位数,最终得到的和将小于原始总数。例如,33.3 + 33.3 + 33.3 = 99.9,33.‾3+ 33.‾3+ 33.‾3 = 100。

因此,您不能将单个百分比四舍五入为n位数,同时仍可获得100的总数保证。你要么心甘情愿地伪造一些数字,要么显示分数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63198916

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档