Sql server 2005 SQL Server:使用数字文本进行计算

Sql server 2005 SQL Server:使用数字文本进行计算,sql-server-2005,floating-point,precision,Sql Server 2005,Floating Point,Precision,我用浮点计算做了一些测试,以尽量减少精度损失。我偶然发现了一个我想在这里展示的现象,希望能得到一个解释 当我写作时 print 1.0 / (1.0 / 60.0) 结果是 60.0024000960 60 当我编写相同的公式并对float print cast(1.0 as float) / (cast(1.0 as float) / cast(60.0 as float)) 结果是 60.0024000960 60 到目前为止,我一直认为带小数点的数字文字会自动被视为具有适当精

我用浮点计算做了一些测试,以尽量减少精度损失。我偶然发现了一个我想在这里展示的现象,希望能得到一个解释

当我写作时

print 1.0 / (1.0 / 60.0)
结果是

60.0024000960
60
当我编写相同的公式并对
float

print cast(1.0 as float) / (cast(1.0 as float) / cast(60.0 as float))
结果是

60.0024000960
60

到目前为止,我一直认为带小数点的数字文字会自动被视为具有适当精度的
float
值。转换为
real
显示与转换为
float
相同的结果

  • 是否有关于SQL Server如何计算数字文字的文档
  • 这些文本属于什么数据类型
  • 我真的必须将它们转换为
    float
    以获得更好的精度吗(这听起来很讽刺:)
  • 有没有比将公式与类型转换混在一起更简单的方法

SQL Server使用尽可能最小的数据类型

当您运行此脚本时

SELECT SQL_VARIANT_PROPERTY(1.0, 'BaseType')
SELECT SQL_VARIANT_PROPERTY(1.0, 'Precision')
SELECT SQL_VARIANT_PROPERTY(1.0, 'Scale')
SELECT SQL_VARIANT_PROPERTY(1.0, 'TotalBytes')
您将看到SQL Server隐式使用了数字(2,1)数据类型。
除以60.0将结果转换为数字(8,6)。
最终计算将结果转换为数值(17,10)


编辑

摘自SQLServer联机丛书

在Transact-SQL语句中,常量 带有一个小数点是自动的 转换为数字数据值, 使用最小精度和刻度 必要的。例如,常数 将12.345转换为精度为5和a的数值 比例为3


是的,为了获得更好的精度,你必须经常施放它们。我的看法是:


我认为应该了解幕后的情况,以便将来在类似情况下参考

带小数点(不包括科学符号)的文字数字值表示十进制数据类型,该数据类型存储为尽可能最小的十进制类型。与Lieven Keersmaekers的引文相同,引自:

在Transact-SQL语句中,带小数点的常量是 使用最小值自动转换为数字数据值 精度和比例是必要的。例如,常数12.345为 转换为精度为5且刻度为3的数值

小数点右侧的尾随零指定比例。小数点左侧的前导零将被忽略

一些例子:

1.0  -> Decimal(2,1)
60.0 -> Decimal(3,1)
1.00 -> Decimal(3,2)
01.0 -> Decimal (2,1)
另一个需要考虑的问题是。 当运算符组合两个不同数据类型的表达式时,数据类型优先级规则指定优先级较低的数据类型转换为优先级较高的数据类型。 还有一点需要考虑的是,如果我们对十进制类型执行算术运算,那么得到的十进制类型,即精度和规模取决于操作数本身和操作本身。本文件对此进行了描述

所以,表达式的一部分在括号中

( 1.0 / 60.0 ) is evaluated to 0.016666 and the resulting type is Decimal (8,6)
使用上述有关小数表达式精度和小数位数的规则。此外,还使用了银行家四舍五入或四舍五入到偶数。需要注意的是,小数和浮点类型的舍入方式不同。 如果我们继续这个表达式

1.0 / 0.016666 is evaluated to 60.002400096 and the resulting type is Decimal (17,10)
因此,差异的部分原因是十进制类型的舍入与浮点类型的舍入不同

根据上述规则,仅在括号内使用一个cast就足够了。根据数据类型优先规则,其他每一个文本都将被提升为float

1.0 / (1.0 / cast(60.0 as float))
还有一件更重要的事。即使这个浮点表达式也不能计算精确的结果。前端(SSMS或其他)将值舍入到(我猜)精度6位,然后截断尾随的零。因此,即1.000001变为1


很简单,不是吗?

要编写一个常量浮点表达式,请尝试使用科学符号:

选择(1.0E0/(1.0E0/60.0E0))


结果是60。

Ah。。直到现在我才知道那个方法。非常感谢:)所以没有办法通过显式转换来获得预期的结果?有没有其他方法可以告诉SQL Server给定的文本属于(例如)float类型?@VVS,除了您已经在做的显式转换之外,我不知道还有其他方法。SQL Server始终将值解释为数字。如果您自己给值添加精度,例如1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000?@VSS:我添加了对文档的引用。文章中的基本原理是有缺陷的。它基于一些任意值。很容易找到支持十进制类型的反例。这些基于一个实证例子的印度主张本身就是陷阱。