SQL Server ROUND()不适用于以1结尾的FLOAT

时间:2014-03-06 16:55:18

标签: sql rounding

我改变了我的例子以使用FLOAT ......太多人被挂在整个NVARCHAR上。我们不会将数据存储在数据库中作为NVARCHAR。我只是以NVARCHAR为例。我用FLOAT得到了相同的结果。

对于某些FLOAT的

,我们遇到了SQL Server ROUND()的问题

    DECLARE @EXCHANGE_RATE FLOAT
    SET @EXCHANGE_RATE = 1.327810000000000000000
    SELECT ROUND(@EXCHANGE_RATE,6,1)
    SET @EXCHANGE_RATE = 1.327820000000000000000
    SELECT ROUND(@EXCHANGE_RATE,6,1)

第一个返回:1.327809 第二个回报:1.32782

你会认为第一个会返回1.32781,而不是1.327809。

这是ROUND中的功能还是错误?有什么简单的方法吗?

谢谢!

基于Mat的将它们作为DECIMAL投射的想法,这可行......它很丑陋,但有效。我使用10的原因是我查看了我们的数据库,这似乎是我们存储的最长数字。此外,我需要将其转换回FLOAT,因为他们不希望看到任何尾随0的

    DECLARE @EXCHANGE_RATE FLOAT
    SET @EXCHANGE_RATE = 1.327810000000000000000
    SELECT CAST(ROUND(CAST(@EXCHANGE_RATE AS DECIMAL(28,10)),6,1) AS FLOAT)

3 个答案:

答案 0 :(得分:2)

尝试此查询。

SELECT
  ROUND('1.3278100',6,0)                     AS x0,
  ROUND('1.3278200',6,0)                     AS y0,
  ROUND('1.3278100',6,1)                     AS x1,
  ROUND('1.3278200',6,1)                     AS y1,

  ROUND(CAST( '1.3278100' AS FLOAT), 6, 0)   AS a0,
  ROUND(CAST( '1.3278200' AS FLOAT), 6, 0)   AS b0,
  ROUND(CAST( '1.3278100' AS FLOAT), 6, 1)   AS a1,
  ROUND(CAST( '1.3278200' AS FLOAT), 6, 1)   AS b1,

  ROUND(CAST( '1.3278100' AS DECIMAL(9,8)), 6, 0)   AS i0,
  ROUND(CAST( '1.3278200' AS DECIMAL(9,8)), 6, 0)   AS j0,
  ROUND(CAST( '1.3278100' AS DECIMAL(9,8)), 6, 1)   AS i1,
  ROUND(CAST( '1.3278200' AS DECIMAL(9,8)), 6, 1)   AS j1
;

http://sqlfiddle.com/#!6/d41d8/15607

这对我说明ROUND()在截断它们之前隐式将VARCHAR值转换为FLOAT

由于FLOAT无法准确表示1.327810,您实际上是截断1.3278099999999(或类似的东西)。

因此,简而言之,在截断之前将它们显式地转换为DECIMAL。或者只是不将数字数据存储为字符串......

答案 1 :(得分:0)

我现在暂时离开这里,这是事实,但这不是op问题的原因。 正确的答案是MatBailie提供的答案 - nVarChar字符串被转换为float,然后截断操作将其减少到下一个较低的值...

来自MSDN的Round function

功能
是要执行的操作类型。 function必须是tinyint,smallint或int。省略function或者值为0(默认值)时,numeric_expression将四舍五入。 *如果指定的值不是0,则会截断numeric_expression。*

试试这个,它显示了不同之处:

DECLARE @EXCHANGE_RATE NVARCHAR(200)
SET @EXCHANGE_RATE = '1.3278100'
SELECT ROUND(@EXCHANGE_RATE,6,0) Rounded,
       ROUND(@EXCHANGE_RATE,6,1) Truncated

SET @EXCHANGE_RATE = '1.327810000001'
SELECT ROUND(@EXCHANGE_RATE,6,0) Rounded,
       ROUND(@EXCHANGE_RATE,6,1) Truncated

输出类型由输入确定...在这种情况下,输入为“1.3278100”,因此该值将转换为数字数据类型,其精度基于字符串中的有效位数(' 1.3278100'有5位有效数字)所以输出类型确定为数字(6,5)或类似的东西......这会导致意外截断。这之前我已经咬过我了。

答案 2 :(得分:0)

使用ROUND(@var,6)代替ROUND(@var,6,1)ROUND()函数中有第3个可选参数,看起来你不需要它。