7

我理解在比较浮点数时存在的许多问题,并感叹它们在这种情况下的使用——但我不是表格作者,只有一个小障碍要爬......

有人决定使用浮点数,因为您希望使用 GUID。我需要检索具有特定浮点值的所有记录。

sp_help MyTable

-- Column_name  Type    Computed    Length  Prec
-- RandomGrouping   float   no  8   53   

这是我天真的尝试:

--yields no results
SELECT RandomGrouping
FROM MyTable
WHERE RandomGrouping = 0.867153569942739

这是一个大致可行的尝试:

--yields 2 records
SELECT RandomGrouping
FROM MyTable
WHERE RandomGrouping BETWEEN 0.867153569942739 - 0.00000001
      AND 0.867153569942739 + 0.00000001

--  0.867153569942739
--  0.867153569942739

在我天真的尝试中,该文字是浮点文字吗?或者它真的是一个稍后转换的十进制文字?

如果我的文字不是浮点文字,那么制作浮点文字的语法是什么?

编辑:我想到了另一种可能性......可能是比显示的更精确的数字存储在此列中。可能无法创建表示此数字的文字。我将接受证明情况如此的答案。


编辑:对 DVK 的回应。

TSQL 是 MSSQLServer 的 SQL 方言。

该脚本有效,因此可以在浮点类型之间确定性地执行相等:

DECLARE @X float
SELECT top 1 @X = RandomGrouping
FROM MyTable
WHERE RandomGrouping BETWEEN 0.839110948199148 - 0.000000000001
  AND 0.839110948199148 + 0.000000000001
  --yields two records
SELECT *
FROM MyTable
WHERE RandomGrouping = @X

我说“大约”是因为该方法测试了一个范围。使用这种方法,我可以获得不等于我预期值的值。

链接的文章不适用,因为我没有(故意)试图跨越小数和浮点数之间的世界界限。我正在尝试只使用花车。这与小数不能转换为浮点数无关。


对辛隆的回应:

可以找到我的记录的文字值,谢谢。

DECLARE @Y binary(8)
SET @Y = 0x3FEAD9FF34076378

SELECT *
FROM MyTable
WHERE convert(binary(8), RandomGrouping) = @Y
4

3 回答 3

5

该文字是浮点文字吗?或者它真的是一个稍后转换的十进制文字?

如果我的文字不是浮点文字,那么制作浮点文字的语法是什么?

SQL Server 中的0.867153569942739文字是一种decimal类型,而不是float. 引擎会自动选择适当的比例和精度来表示给定的文字。

要编写该float类型的文字,您应该使用科学记数法,如下所示: 0.867153569942739E0

这记录在常量 (Transact-SQL)中

十进制常数

十进制常量由一串数字表示,这些数字不包含在引号中并包含小数点。以下是十进制常量的示例:

1894.1204  
2.0  

浮点数和实数常数

浮点数实数常数使用科学计数法表示。以下是浮点数值的示例:

101.5E5  
0.5E-2

sp_describe_first_result_set可以告诉我们列的类型

EXEC sp_describe_first_result_set N'SELECT 0.867153569942739, 0.867153569942739E0'

它返回numeric(15,15)第一列和float第二列。


如果您的列RandomGrouping被索引,使用文字会更有效float,因为当您换行时RandomGroupingconvert()无法使用索引。

以下查询将使用索引:

SELECT *
FROM MyTable
WHERE RandomGrouping = 0.867153569942739E0

以下查询将不使用索引:

SELECT *
FROM MyTable
WHERE convert(binary(8), RandomGrouping) = @Y
于 2019-03-03T23:45:48.660 回答
2

显示的值可能会被截断。我假设该列没有唯一约束,否则问题将没有实际意义。在我的设置中,SSMS 会截断此脚本中更精确的值。

create table flt ( f float not null primary key )
insert into flt
select 0.111111111111111
union all
select 0.1111111111111111
select f, cast(f as binary(8)) from flt

同样,如果这些值不同,您可以将它们转换为 binary(8) 并根据该值识别它们,如下所示:

select f from flt
where cast(f as binary(8)) = 0x3FBC71C71C71C71C
于 2010-06-11T17:58:29.770 回答
0

问题不在于它是否是浮点文字。

问题是在 Sybase(或任何数据库服务器)中比较两个浮点数是否相等不是确定性的,因为 4.00000000000000000000... 和 3.999999999999999999999... 是相同的确切数字但不相等。

您的第二个解决方案是比较浮点数是否“相等”的唯一正确方法(也就是说,它们是否相同)。

你为什么说你的第二种方法“几乎有效”?

由于您没有提供您使用的特定数据库服务器,因此这里有一个相当不错的 MySQL 问题写法(与上面的结论基本相同)

http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html

于 2010-06-11T17:14:59.540 回答