【问题标题】:SQL Server 2014 rounding a float gives unexpected resultSQL Server 2014 舍入浮点数会产生意外结果
【发布时间】:2020-09-03 21:12:03
【问题描述】:

谁能解释以下查询的结果?我认为这是 SQL Server 2014 中的一个错误。

DECLARE @x float
SET @x=58.415
SELECT ROUND(58.415,2), ROUND(@x,2)

【问题讨论】:

标签: sql sql-server tsql sql-server-2014 reporting


【解决方案1】:

因为第一个参数存储为十进制(5,3):

EXEC sp_describe_first_result_set N'SELECT 58.415 x', null, 0;  

您有两个不同的代码:

DECLARE @x float 
SET @x=58.415 
SELECT ROUND(58.415,2), ROUND(@x,2)

GO

DECLARE @x decimal(19,3)
SET @x=58.415 
SELECT ROUND(58.415,2), ROUND(@x,2)


GO

基本上,浮动是

用于浮点数值的近似数数据类型 数据。浮点数据是近似的;因此,并非所有值 数据类型范围可以精确表示。

@Zohar 所做的改进解释了为什么值为converted to decimal

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

【讨论】:

  • 您可能想要添加来自here: 的引号在 Transact-SQL 语句中,使用最小精度和所需的小数位数自动将带小数点的常量转换为数字数据值.例如,常数 12.345 被转换为精度为 5、小数位数为 3 的数值。
  • 我已经编辑了几个错别字(包括我的名字)。希望你不介意:-)
【解决方案2】:

您所看到的解释是浮点运算在 SQL Server(或任何其他数据库或编程语言)中并不精确。以下是实际发生的情况,显示“真实”值以供解释:

SELECT
    ROUND(58.415, 2),           -- rounds UP to 58.420, this is DECIMAL(10,3), EXACT
    ROUND(58.4149999999999, 2)  -- rounds DOWN to 58.41

这里的问题是当您进行以下变量赋值时:

DECLARE @x float
SET @x = 58.415

在内部,SQL Server 实际上将值存储为近似值,类似于58.41499999999。然后,当四舍五入到小数点后两位时,您会得到58.41

一般来说,如果您需要精确的精度,您应该使用精确的类型。在这种情况下,DECIMAL(10,3) 可以工作。

【讨论】:

  • 虽然浮点运算确实不准确,但这不是原因。在这种情况下,gotqn 的答案是正确的 - 请参阅 here
  • @ZoharPeled 不,我的回答是正确的,除了我没有提到默认文字被视为十进制。但是,从查询的行为中可以明显看出这一点。
  • 其实我仔细想一想,其实是你和qotqn的答案的结合,给出了一个完整准确的解释:你对SQL Server如何存储float值是正确的@987654327 @,而 gotqn 关于为什么在使用数字文字时准确存储它是正确的......
  • @ZoharPeled 是的……我就是这么想的。不知道十进制文字默认为 DECIMAL 类型,但我想这也是正确解释的一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
相关资源
最近更新 更多