SQL Server Strange Ceiling()行为

时间:2014-10-02 16:35:39

标签: sql sql-server sql-server-2012

任何人都可以在SQL Server中解释以下结果吗?我很难过。

declare @mynum float = 8.31

select ceiling( @mynum*100)

831

中的结果
declare @mynum float = 8.21

select ceiling( @mynum*100)

822

中的结果

我测试了一系列数字(SQL Server 2012)。有些增加而其他人保持不变。我不知道为什么天花板会以不同的方式处理其中一些。从float更改为decimal(18,5)似乎可以解决问题,但我担心可能会有其他因素而导致这样做。任何解释都会有所帮助。

2 个答案:

答案 0 :(得分:3)

我认为这称为浮点精度。您几乎可以在所有编程语言和数据库中找到它。这是因为数据仅以一定的精度存储,实际上您设置为8.31的可能不是8.31,而是例如8.31631312381813,并且当它与ceil相乘时,它可能会导致不同的值出现。

SQL server documentation page ,您可以阅读:

  

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

在其他数据库系统中存在同样的问题。例如,在mysql website,您可以阅读:

  

浮点数有时会引起混淆,因为它们是近似值而不是存储为精确值。在SQL语句中写入的浮点值可能与内部表示的值不同。尝试将浮点值视为比较中的精确值可能会导致问题。它们还受平台或实现依赖性的影响。 FLOAT和DOUBLE数据类型受这些问题的影响。对于DECIMAL列,MySQL执行精度为65位十进制数的操作,这可以解决最常见的不准确问题。

答案 1 :(得分:0)

浮点数不是100%准确。就像MarcinNabiałek所写的8.31你看到的可能是其他东西,比如8.310000000001。有关浮点精度问题的一些有趣读物,请参阅here

解决方案不使用浮点数据类型,除非你真的需要。您应该使用DECIMALMONEY数据类型。

如果您真的必须使用浮点数据类型,那么您可以在每{{1}之前添加或减去一个小值(精确度thresold或 epsilon ) }},floor或比较操作以获得所需的精度。如果你有很多浮点运算,那么编写你自己的floating point comparison functions可能是值得的。