Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server浮点不稳定的最后数字_Sql_Sql Server_Python 3.x_Floating Accuracy_Pypyodbc - Fatal编程技术网

SQL Server浮点不稳定的最后数字

SQL Server浮点不稳定的最后数字,sql,sql-server,python-3.x,floating-accuracy,pypyodbc,Sql,Sql Server,Python 3.x,Floating Accuracy,Pypyodbc,在SQLServer中,我创建了一个聚合列(我添加的其他列的组合、multiple、sum等),它是SQL数据类型float 但是,当我多次运行同一个查询时,我的浮点值的最后两位数是不稳定的,并且一直在变化 在浮点数下面是随机的最后两位数字——我尝试转换成十进制,然后切掉最后两位数字 select round(convert(decimal(20,19), 0.0020042890676442646), 17,1) select round(convert(decimal(20,19), 0.0

在SQLServer中,我创建了一个聚合列(我添加的其他列的组合、multiple、sum等),它是SQL数据类型float

但是,当我多次运行同一个查询时,我的浮点值的最后两位数是不稳定的,并且一直在变化

在浮点数下面是随机的最后两位数字——我尝试转换成十进制,然后切掉最后两位数字

select round(convert(decimal(20,19), 0.0020042890676442646), 17,1)
select round(convert(decimal(20,19), 0.0020042890676442654), 17,1)
在SSMS中,两者的结果均为:0.0020042890676442600

请注意,这里的输入常量来自python,因此它们可能已经被修改过了。我不能直接从sql中获取它们,因为获得计算异常是非常罕见的,而且我不知道如何重现它

但是通过pyodbc运行到python,有时结果是python decimal.decimal类型,第二条语句的值为0.0020042890676442700,因此它似乎进行舍入而不是截断

我还注意到,sql中的计算结果并不总是相同的,并且在浮点的最后一个数字中存在不稳定性-但不确定如何从系统上测试这一点

转换为浮动的常数给出:

select convert(float,0.0020042890676442646)
select convert(float,0.0020042890676442654)
结果:0.00200428906764427

以小数为单位,四舍五入:

select round(convert(decimal(20,19), convert(float,0.0020042890676442646)), 17,1)
select round(convert(decimal(20,19), convert(float,0.0020042890676442654)), 17,1)
在这两种情况下,SSMS的结果均为:0.0020042890676442700

我尝试直接发回浮点数,而不是强制转换为十进制,但似乎在到达python时,两个不稳定的数字总是添加在末尾。即使截断也没有帮助,其他随机数也会被添加

似乎python在传输过程中以随机方式修改了float和Decimal,或者sql中已经存在不稳定性,或者两者都存在

我尝试在python端截断np.float64,如下所示:


但是,由于sql中的最后一个浮点数可能在e15和e19之间,除非我将所有内容都放在e15上,否则无法设置一致的截断级别。

聚合的处理顺序是未定义的,就像任何查询的结果顺序是未定义的一样,除非使用
order BY
子句。在
float
s的情况下,顺序很重要。可以使用
OVER
子句强制执行聚合处理顺序。下面是一些要演示的代码:

 -- demonstrate that order matters when adding floats

declare @a float
declare @b float
declare @c float
declare @d float
declare @e float

set @a = 1
set @b = 1
set @c = 9024055778268167

-- add A to B, and then add C
-- result is 9024055778268170

set @d = @a + @b

set @e = @d + @c

select cast( @e as decimal(38,0) )

-- add C to B, and then add A
-- result is 9024055778268168

set @d = @c + @b

set @e = @d + @a

select cast( @e as decimal(38,0) )

-- put these values into a table

create table OrderMatters ( x float )

insert into OrderMatters ( x ) values ( @a )
insert into OrderMatters ( x ) values ( @b )
insert into OrderMatters ( x ) values ( @c )

declare @x float

-- add them in ascending order
-- result is 9024055778268170

select @x = sum(x) over (order by x asc ) from OrderMatters

select cast(@x as decimal(38,0))

-- add them in descending order
-- result is 9024055778268168

select @x = sum(x) over (order by x desc ) from OrderMatters

select cast(@x as decimal(38,0))

聚合的处理顺序是未定义的,这与任何查询结果的顺序都是未定义的一样,除非使用
orderby
子句。在
float
s的情况下,顺序很重要。可以使用
OVER
子句强制执行聚合处理顺序。下面是一些要演示的代码:

 -- demonstrate that order matters when adding floats

declare @a float
declare @b float
declare @c float
declare @d float
declare @e float

set @a = 1
set @b = 1
set @c = 9024055778268167

-- add A to B, and then add C
-- result is 9024055778268170

set @d = @a + @b

set @e = @d + @c

select cast( @e as decimal(38,0) )

-- add C to B, and then add A
-- result is 9024055778268168

set @d = @c + @b

set @e = @d + @a

select cast( @e as decimal(38,0) )

-- put these values into a table

create table OrderMatters ( x float )

insert into OrderMatters ( x ) values ( @a )
insert into OrderMatters ( x ) values ( @b )
insert into OrderMatters ( x ) values ( @c )

declare @x float

-- add them in ascending order
-- result is 9024055778268170

select @x = sum(x) over (order by x asc ) from OrderMatters

select cast(@x as decimal(38,0))

-- add them in descending order
-- result is 9024055778268168

select @x = sum(x) over (order by x desc ) from OrderMatters

select cast(@x as decimal(38,0))

. . 我认为你的代码中没有任何浮动。我认为,常量被解释为小数。您可以使用
sp_descripe_first_result_set
看到SQL Server将这两个文本解释为
numeric(19,19)
:EXEC sp_descripe_first_result_set N'SELECT 0.0020042890676442646';EXEC sp_description_first_result_set N'SELECT 0.0020042890676442654';。python似乎在背后做一些事情。第一个问题是,为什么聚合会在不同的时间给出不同的答案?在计算聚合时,不能保证每次都以相同的顺序处理记录,就像在任何查询中都不能保证顺序一样,除非使用order BY。在浮点数上进行数学运算时,顺序可能很重要。如果您有一个浮点数列表,并从最小值开始添加,则可以得到与从最大值开始添加不同的答案。在SQL Server中,浮点数仅精确到15位。如果你有更多的,精度将丢失。这是有据可查的。@KaiAeberli-小数点分隔符后有17位数字,但前两个零不是有效数字,它们只是浮点值2.00428906764426E-3的缩放(指数)的结果。我认为你的代码中没有任何浮动。我认为,常量被解释为小数。您可以使用
sp_descripe_first_result_set
看到SQL Server将这两个文本解释为
numeric(19,19)
:EXEC sp_descripe_first_result_set N'SELECT 0.0020042890676442646';EXEC sp_description_first_result_set N'SELECT 0.0020042890676442654';。python似乎在背后做一些事情。第一个问题是,为什么聚合会在不同的时间给出不同的答案?在计算聚合时,不能保证每次都以相同的顺序处理记录,就像在任何查询中都不能保证顺序一样,除非使用order BY。在浮点数上进行数学运算时,顺序可能很重要。如果您有一个浮点数列表,并从最小值开始添加,则可以得到与从最大值开始添加不同的答案。在SQL Server中,浮点数仅精确到15位。如果你有更多的,精度将丢失。这是有据可查的。@KaiAeberli-小数点分隔符后有17位数字,但前两个零不是有效数字,它们只是浮点值缩放(指数)的结果:2.00428906764426E-3这回答了我的python代码的一个问题,我已将a+b重构为b+a,因此不精确。另一个问题是:SQL中的计算浮点被错误地转换为python。我最终只是通过ODBC传输整数,并在python中计算浮点数,因此不需要从sql浮点转换为np.float64,这似乎造成了不精确性。这回答了我python代码的一个问题,我将a+b重构为b+a,从而导致了不精确性。另一个问题是:SQL中的计算浮点被错误地转换为python。我最终只是通过ODBC传输整数,并在python中计算浮点,因此不需要从sql浮点转换为np.float64,这似乎造成了不精确性。