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

Rounding currency to add up to the total value

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

当四舍五入到小数点后两位表示货币时,it = .29。 但是 .29*3=3.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, 153.88 as sales_tax, round(153.88 /3,2) as rounded
union all
select '3' as item_number, 153.88 as sales_tax, round(153.88 /3,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`
)   

如果应用于您问题中的示例数据 - 输出为

下一个运行输出

还有下一个运行 ...

因此,如您所见 - 额外的美分是随机应用的 - 与 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;

我举了一个例子,其中分布有所不同。