2014-10-02 63 views
1

任何人都可以在SQL Server中解释以下结果吗?我很难过。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)似乎解决了这个问题,但我很谨慎,可能会有其他影响,因此我错过了。任何解释都会有所帮助。

+1

你为什么使用浮动?我不知道切换到十进制的任何影响,除非你必须输入更多,并且会有更多的可预测的准确性。去做就对了。请参阅[本文](http://databases.aspfaq.com/database/what-datatype-should-i-use-for-numeric-columns.html),[本文](http://classicasp.aspfaq。 com/general/why-does-3-2-1-5-4-7000000000000002.html),[本文](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/12/bad-习惯性地使用错误的数据类型.aspx)和[本问答](http://stackoverflow.com/q/1355418/61305)。 – 2014-10-02 16:41:40

+0

Thx为物品。 – TEIHelp 2014-10-02 17:45:05

回答

3

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

SQL server documentation page你可以阅读:

使用近似数数据类型的浮点数字数据。浮点数据是近似的;因此,数据类型范围中的所有值都不能完全表示。

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

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

+0

@Lasse不同的数字会以不同的方式表示为float。如果8.31实际上被表示为8.3100000000000001,那么你乘以831.000000000001,那么CEILING(831.0000000000001)是什么? 832.如果8.21被表示为8.209999999999 ...等等。 – 2014-10-02 16:45:05

+0

您可能需要[SQL Server文档](http://msdn.microsoft.com/en-us/library/ms173773.aspx)中的此引用,而不是MySQL文档中的任何内容:'大概数字数据类型与浮点数字数据一起使用。浮点数据是近似的;因此,并非数据类型范围中的所有值都可以精确表示。' – 2014-10-02 16:46:52

+0

@Lasse很棒,如果您总是处理值100。 – 2014-10-02 16:54:35

0

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

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

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