为什么即使提供确切的数据,FLOAT类型数据比较也不起作用

时间:2018-01-19 05:32:50

标签: sql sql-server sql-server-2012 floating-point precision

在具有相同值的实际表中

SELECT * FROM float_value WHERE val = 49640.2473896214 -- No data returns

如果我把它四舍五入到总精度那就可以了

SELECT * FROM float_value WHERE ROUND(val, 10) = ROUND(49640.2473896214, 10) --Returning Data

之后我创建了具有相同值49640.2473896214的临时表,并且它在上面失败的第一个查询中有效

CREATE TABLE #testing(Vvalue FLOAT)
INSERT INTO #testing VALUES (49640.2473896214)

SELECT * FROM #testing WHERE Vvalue = 49640.2473896214 -- Simply returning row

请您帮我弄清楚为什么=比较在上面没有效果?如果我总是使用ROUND,那么找出要舍入的精度并进行比较将是另一个问题。

如果我们提供输入字段中确切可见的内容,即= 49640.2473896214应该返回值,我想要结果。

提前谢谢。

3 个答案:

答案 0 :(得分:2)

  

用于浮点数字数据的近似数字数据类型。浮点数据是近似值;因此,并非数据类型范围中的所有值都可以准确表示。   https://docs.microsoft.com/en-us/sql/t-sql/data-types/float-and-real-transact-sql

这可能非常令人沮丧,但是一些浮点值将无法通过相等运算符进行比较,并且必须修复小数精度以确保可靠地使用等号。

答案 1 :(得分:1)

浮点数不能完全代表您想要的值,例如:

  • 49640.2473896214321存储为49640.2473896214287378825247287750244140625
  • 49640.2473896214521存储为49640.247389621450565755367279052734375
  • 17.56被存储为......左侧为练习

值得注意的是,浮点数的显示值通常是近似值。某些环境允许您更改显示值的精度,但我在SQL Server中找不到任何此类设置。说了这么多:

awk: line 1: syntax error at or near ^

这是因为数据库中不存在SELECT * FROM float_value WHERE val = 49640.2473896214 -- No data returns 。数据库中的值可以是49640.2473896214...62139...,谁知道。

  

请你帮我弄明白为什么=比较不是   在上面工作?

如果您提供存储在数据库中的确切值(在以前的INSERT或UPDATE操作中使用),它应该可以工作。如果您在数据库中提供参见的值,请参阅上面的注释。

  

如果我应该总是使用ROUND那么这将是另一个问题   找出要舍入的精度并进行比较。

ROUNDing为FLOAT返回FLOAT,因此您可能会遇到类似的问题。引用最多的解决方案是减去这两个数字并检查差异是否非常小:

...62141...

select * from #testing WHERE ABS(vvalue - 49640.24738962 ) < 1e-11 -- id | vvalue | actual_value -- 1 | 49640.24738962 | 49640.24738962 select * from #testing WHERE ABS(vvalue - 49640.2473896214 ) < 1e-11 -- id | vvalue | actual_value -- 2 | 49640.2473896214 | 49640.2473896214 select * from #testing WHERE ABS(vvalue - 49640.2473896214321) < 1e-11 -- id | vvalue | actual_value -- 3 | 49640.2473896214 | 49640.2473896214321 select * from #testing WHERE ABS(vvalue - 49640.2473896214521) < 1e-11 -- id | vvalue | actual_value -- 4 | 49640.2473896215 | 49640.2473896214521 被称为epsilon,即您可以接受的容差量。你可以将它设置为更小但不小于1e-11的东西。

答案 2 :(得分:0)

现在,我了解FLOAT字段值的情况,即通过舍入给定值来存储高达10的精度

例如:

CREATE TABLE #testing(id INT IDENTITY(1,1), Vvalue FLOAT, actual_value VARCHAR(50))
INSERT INTO #testing VALUES 
(49640.24738962, '49640.24738962'),
(49640.2473896214, '49640.2473896214'),
(49640.2473896214321, '49640.2473896214321'),
(49640.2473896214521, '49640.2473896214521')

值保存为:

id  Vvalue              actual_value
1   49640.24738962      49640.24738962      --Saved same as input
2   49640.2473896214    49640.2473896214    --Saved same as input
3   49640.2473896214    49640.2473896214321 --Saved upto 10 precision only by rounding leaving trailing zeros
4   49640.2473896215    49640.2473896214521 --Saved upto 10 precision only by rounding leaving trailing zeros

现在,显然跟随查询应返回两行2,3但行3的值不完全是输出

SELECT * FROM #testing WHERE Vvalue = 49640.2473896214 

id  Vvalue              actual_value
2   49640.2473896214    49640.2473896214

在我的情况下,它应该返回2,3行,所以,如果我将比较列值乘以10,那么它将给出我想要的东西,它对我来说并不重要,它是什么看不见的值&#39抱着?我只是想收到表格中的内容

SELECT * FROM #testing WHERE ROUND(Vvalue, 10) = 49640.2473896214

id  Vvalue              actual_value
2   49640.2473896214    49640.2473896214
3   49640.2473896214    49640.2473896214321

感谢大家分享您的想法并提升我的想法:)