浮动不一致的平均值
Avg of float inconsistency
select return 正好在 23,000 行
除了 return 60 到 200 行之间(而不是相同的行)
except 应该 return 0 因为它是 select a except select a
PK: [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
[tf] 是一个浮点数,我得到的浮点数不准确
但我天真地认为 avg(float) 是可重复的
Avg(float) 似乎是可重复的
解决方法是什么?
TF 介于 0 和 1 之间,我只需要 5 位有效数字
我只需要 avg(TF) 是相同的数字 运行 运行
Decimal(9,8) 给了我足够的精度,如果我转换为 decimal(9,8) 除了正确 returns 0
我可以将 [TF] 更改为 decimal(9,8) 但这将是一些工作和大量回归测试,因为一些使用 [tf] 的测试需要一天的时间才能达到 运行
将 [TF] 更改为 decimal(9,8) 是最佳解决方案吗?
SELECT [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
, avg([FTSindexWordOnce].[tf]) AS [avgTFraw]
FROM [docSVenum1]
JOIN [docFieldLock]
ON [docFieldLock].[sID] = [docSVenum1].[sID]
AND [docFieldLock].[fieldID] = [docSVenum1].[enumID]
AND [docFieldLock].[lockID] IN (4, 5) /* secLvl docAdm */
JOIN [FTSindexWordOnce]
ON [FTSindexWordOnce].[sID] = [docSVenum1].[sID]
GROUP BY [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
except
SELECT [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
, avg([FTSindexWordOnce].[tf]) AS [avgTFraw]
FROM [docSVenum1]
JOIN [docFieldLock]
ON [docFieldLock].[sID] = [docSVenum1].[sID]
AND [docFieldLock].[fieldID] = [docSVenum1].[enumID]
AND [docFieldLock].[lockID] IN (4, 5) /* secLvl docAdm */
JOIN [FTSindexWordOnce]
ON [FTSindexWordOnce].[sID] = [docSVenum1].[sID]
GROUP BY [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
order by [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
在这种情况下,tf 是 tf-idf
的词频
tf归一化是主观的,不需要太多精度
Avg(tf) 需要从 select 到 select 保持一致,否则结果不一致
在带有连接的单个 select 中,我需要一个一致的 avg(tf)
使用小数和 tf 的低精度得到了一致的结果
这非常类似于:SELECT SUM(...) is non-deterministic when adding the column-values of datatype float
。
问题在于,对于不准确的数据类型 (FLOAT/REAL
),浮点数算术运算的顺序很重要。来自连接的演示:
DECLARE @fl FLOAT = 100000000000000000000
DECLARE @i SMALLINT = 0
WHILE (@i < 100)
BEGIN
SET @fl = @fl + CONVERT(float, 5000)
SET @i = @i + 1
END
SET @fl = @fl - 100000000000000000000
SELECT CONVERT(NVARCHAR(40), @fl, 2)
-- 0.000000000000000e+000
DECLARE @fl FLOAT = 0
DECLARE @i SMALLINT = 0
WHILE (@i < 100)
BEGIN
SET @fl = @fl + CONVERT(float, 5000)
SET @i = @i + 1
END
SET @fl = @fl + 100000000000000000000
SET @fl = @fl - 100000000000000000000
SELECT @fl
-- 507904
可能的解决方案:
CAST
准确数据类型的所有参数,如 DECIMAL/NUMERIC
- 更改table并将
FLOAT
更改为DECIMAL
- 您可以尝试强制查询优化器以相同的顺序计算总和。
The good news is that when a stable query result matters to your
application, you can force the order to be the same by preventing
parallelism with OPTION (MAXDOP 1).
看起来 initial link 已经死了。 WebArchive
select return 正好在 23,000 行
除了 return 60 到 200 行之间(而不是相同的行)
except 应该 return 0 因为它是 select a except select a
PK: [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
[tf] 是一个浮点数,我得到的浮点数不准确
但我天真地认为 avg(float) 是可重复的
Avg(float) 似乎是可重复的
解决方法是什么?
TF 介于 0 和 1 之间,我只需要 5 位有效数字
我只需要 avg(TF) 是相同的数字 运行 运行
Decimal(9,8) 给了我足够的精度,如果我转换为 decimal(9,8) 除了正确 returns 0
我可以将 [TF] 更改为 decimal(9,8) 但这将是一些工作和大量回归测试,因为一些使用 [tf] 的测试需要一天的时间才能达到 运行
将 [TF] 更改为 decimal(9,8) 是最佳解决方案吗?
SELECT [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
, avg([FTSindexWordOnce].[tf]) AS [avgTFraw]
FROM [docSVenum1]
JOIN [docFieldLock]
ON [docFieldLock].[sID] = [docSVenum1].[sID]
AND [docFieldLock].[fieldID] = [docSVenum1].[enumID]
AND [docFieldLock].[lockID] IN (4, 5) /* secLvl docAdm */
JOIN [FTSindexWordOnce]
ON [FTSindexWordOnce].[sID] = [docSVenum1].[sID]
GROUP BY [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
except
SELECT [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
, avg([FTSindexWordOnce].[tf]) AS [avgTFraw]
FROM [docSVenum1]
JOIN [docFieldLock]
ON [docFieldLock].[sID] = [docSVenum1].[sID]
AND [docFieldLock].[fieldID] = [docSVenum1].[enumID]
AND [docFieldLock].[lockID] IN (4, 5) /* secLvl docAdm */
JOIN [FTSindexWordOnce]
ON [FTSindexWordOnce].[sID] = [docSVenum1].[sID]
GROUP BY [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
order by [docSVenum1].[enumID], [docSVenum1].[valueID], [FTSindexWordOnce].[wordID]
在这种情况下,tf 是 tf-idf
的词频
tf归一化是主观的,不需要太多精度
Avg(tf) 需要从 select 到 select 保持一致,否则结果不一致
在带有连接的单个 select 中,我需要一个一致的 avg(tf)
使用小数和 tf 的低精度得到了一致的结果
这非常类似于:SELECT SUM(...) is non-deterministic when adding the column-values of datatype float
。
问题在于,对于不准确的数据类型 (FLOAT/REAL
),浮点数算术运算的顺序很重要。来自连接的演示:
DECLARE @fl FLOAT = 100000000000000000000
DECLARE @i SMALLINT = 0
WHILE (@i < 100)
BEGIN
SET @fl = @fl + CONVERT(float, 5000)
SET @i = @i + 1
END
SET @fl = @fl - 100000000000000000000
SELECT CONVERT(NVARCHAR(40), @fl, 2)
-- 0.000000000000000e+000
DECLARE @fl FLOAT = 0
DECLARE @i SMALLINT = 0
WHILE (@i < 100)
BEGIN
SET @fl = @fl + CONVERT(float, 5000)
SET @i = @i + 1
END
SET @fl = @fl + 100000000000000000000
SET @fl = @fl - 100000000000000000000
SELECT @fl
-- 507904
可能的解决方案:
CAST
准确数据类型的所有参数,如DECIMAL/NUMERIC
- 更改table并将
FLOAT
更改为DECIMAL
- 您可以尝试强制查询优化器以相同的顺序计算总和。
The good news is that when a stable query result matters to your application, you can force the order to be the same by preventing parallelism with OPTION (MAXDOP 1).
看起来 initial link 已经死了。 WebArchive