四舍五入货币加起来总价值
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;
我举了一个例子,其中分布有所不同。
我有一个销售税值,我需要将其平均分配给 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;
我举了一个例子,其中分布有所不同。