总和分配的值问题(处理四舍五入错误)
-
24-10-2019 - |
题
我有一个价格为4欧元的产品,我需要为3个部门分配这笔钱。在第二列上,我需要获取该产品的行数,并为部门数量划分。
我的查询:
select
department, totalvalue,
(totalvalue / (select count(*) from departments d2 where d2.department = p.product))
dividedvalue
from products p, departments d
where d.department = p.department
Department Total Value Divided Value
---------- ----------- -------------
A 4 1.3333333
B 4 1.3333333
C 4 1.3333333
但是,当我总结值时,我会得到3,999999。当然,有数百行我会得到很大的差异...是否有机会定义2个小数数和最后一个值? (我的结果是1.33 1.33 1.34)我的意思是,某种方法可以调整最后一行?
解决方案
有六个精度的小数,如果您将最终数字围绕两个小数,则需要大约5,000件交易才能注意到一分钱。将小数的数量增加到可接受的水平将消除大多数问题,即使用9个小数,您需要大约5,000,000件交易才能注意到一分钱。
其他提示
也许您可以制作总计的第四行 - 总和(a,b,c)。但这取决于您想做什么,如果您需要确切的价值,则可以保持分数,否则,不关心虚拟损失
也可以简单地将特定值的舍入差异添加到要舍入的下一个数字(在舍入之前)。这样,桩始终保持相同的大小。
这是由TSQL(Microsoft SQL Server)实现的 马丁:
-- Set parameters.
DECLARE @departments INTEGER = 3;
DECLARE @totalvalue DECIMAL(19, 7) = 4.0;
WITH
CTE1 AS
(
-- Create the data upon which to perform the calculation.
SELECT
1 AS Department
, @totalvalue AS [Total Value]
, CAST(@totalvalue / @departments AS DECIMAL(19, 7)) AS [Divided Value]
, CAST(ROUND(@totalvalue / @departments, 2) AS DECIMAL(19, 7)) AS [Rounded Value]
UNION ALL
SELECT
CTE1.Department + 1
, CTE1.[Total Value]
, CTE1.[Divided Value]
, CTE1.[Rounded Value]
FROM
CTE1
WHERE
Department < @departments
),
CTE2 AS
(
-- Perform the calculation for each row.
SELECT
Department
, [Total Value]
, [Divided Value]
, [Rounded Value]
, CAST([Divided Value] - [Rounded Value] AS DECIMAL(19, 7)) AS [Rounding Difference]
, [Rounded Value] AS [Calculated Value]
FROM
CTE1
WHERE
Department = 1
UNION ALL
SELECT
CTE1.Department
, CTE1.[Total Value]
, CTE1.[Divided Value]
, CTE1.[Rounded Value]
, CAST(CTE1.[Divided Value] + CTE2.[Rounding Difference] - ROUND(CTE1.[Divided Value] + CTE2.[Rounding Difference], 2) AS DECIMAL(19, 7))
, CAST(ROUND(CTE1.[Divided Value] + CTE2.[Rounding Difference], 2) AS DECIMAL(19, 7))
FROM
CTE2
INNER JOIN CTE1
ON CTE1.Department = CTE2.Department + 1
)
-- Display the results with totals.
SELECT
Department
, [Total Value]
, [Divided Value]
, [Rounded Value]
, [Rounding Difference]
, [Calculated Value]
FROM
CTE2
UNION ALL
SELECT
NULL
, NULL
, SUM([Divided Value])
, SUM([Rounded Value])
, NULL
, SUM([Calculated Value])
FROM
CTE2
;
输出:
您可以插入顶部想要的任何数字。我不确定该算法是否有数学证明。
不隶属于 StackOverflow