四舍五入货币以加起来总价值

问题描述

我有一个销售税值,我需要将其平均分配到 3 个项目中。 例如:$153.88/3 = 51.29333333333333

四舍五入到小数点后两位表示货币时,it = $51.29。 但是 $51.29*3=$153.87 比总税额低 1 美分。

是否有一个函数可以解决这些舍入误差,以便各个值总和总和?那么额外的 1 美分会随机分配给 1/3 的物品吗?

select '1' as item_number,153.88 as sales_tax,round(153.88 /3,2) as rounded
union all
select '2' as item_number,2) as rounded
union all
select '3' as item_number,2) as rounded
     

解决方法

考虑以下

select * except(pre_split,pos),round(if(pos > round(100 * (sales_tax - sum(pre_split) over()),2),pre_split,pre_split + .01),2) final_split
from (
  select *,round(sales_tax / count(1) over(),2) pre_split,row_number() over(order by rand()) pos
  from `project.dataset.table`
)   

如果适用于您问题中的样本数据 - 输出为

enter image description here

下一次运行输出

enter image description here

下一次运行...

enter image description here

所以,正如你所看到的 - 额外的分是随机应用的 - 与 rand() 函数的运行一样随机 :o))

此外,如果超过一美分 - 所有美分也将均匀随机地应用

,

这是一个棘手的问题。使用 floor()ceil()round() 获得近似解决方案非常简单。然后,您甚至可以将“额外”添加到其中一行。

然而,额外的可能超过 0.01,这开始看起来很尴尬。当您拥有三个项目时不会发生这种情况,但可能会发生更多。我更喜欢将它们均匀地分布在行上。

所以,我建议:

with t as (
      select '1' as item_number,153.89 as sales_tax
      union all
      select '2' as item_number,153.89 as sales_tax
      union all
      select '3' as item_number,153.89 as sales_tax
      union all
      select '4' as item_number,153.89 as sales_tax
      union all
      select '5' as item_number,153.89 as sales_tax
      union all
      select '6' as item_number,153.89 as sales_tax
      union all
      select '7' as item_number,153.89 as sales_tax
)
select t.*,(floor(sales_tax * 100 / count(*) over ()) +
        (case when floor(sales_tax * 100 / count(*) over ()) * count(*) over () +
                   row_number() over ()  - 1 < sales_tax * 100
              then 1 else 0
         end)
       ) / 100.0
from t;

我已经包含了一个示例,其中分布会产生影响。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...