SQL Server舍入和截断问题

时间:2018-09-07 14:57:49

标签: sql-server sql-server-2014 rounding

因此,在四舍五入过程中,我遇到了SQL Server中一个奇怪的问题。

这是我的例子:

declare @amount float = 178.69999999

select
    @amount as [amount],
    round(@amount, 6) as [round],
    round(round(@amount, 6), 2, 1) as [trim_1],
    floor(round(@amount, 6) * power(10.0, 2)) / power(10.0, 2) as [trim_2]

这是我得到的结果:

+--------------+-------+--------+--------+
|    amount    | round | trim_1 | trim_2 |
+--------------+-------+--------+--------+
| 178.69999999 | 178.7 | 178.69 | 178.7  |
+--------------+-------+--------+--------+

这里的一般想法是我试图四舍五入到小数点后六位,然后修剪/下限/截断两位小数位。这意味着我期望得到178.7的结果,但是我得到178.69的{​​{1}}的结果(trim_1是另一种产生相同结果的方法结果)。

据我所知,正如SQL Server documentation所述,我正在适当地使用trim_2函数:

  

语法

round
     

功能

     

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

所以我希望ROUND ( numeric_expression , length [ ,function ] ) trim_1相匹配。

这是关键:如果我将trim_2的结果作为常量而不是变量传递,则它按预期方式工作:

round

我的猜测是SQL Server的浮点运算有些奇怪,或者我设法以某种方式错过了某些东西。对于它的价值,我正在使用SQL Server 2014,所以也许这就是我的问题。

我希望使用尽可能少的代码来获得select round(178.7, 2, 1) -- Yields 178.7 的结果,以便最终结果看起来更简洁。

1 个答案:

答案 0 :(得分:2)

使用decimal代替float

取自Float and Real (Transact-SQL)

  

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

在您的代码中用float替换decimal会得到期望的结果:

declare @amount decimal(18, 10) = 178.69999999

select
    @amount as [amount],
    round(@amount, 6) as [round],
    round(round(@amount, 6), 2, 1) as [trim_1],
    floor(round(@amount, 6) * power(10.0, 2)) / power(10.0, 2) as [trim_2]

结果:

╔════════════════╦════════════════╦════════════════╦════════════╗
║     amount     ║     round      ║     trim_1     ║   trim_2   ║
╠════════════════╬════════════════╬════════════════╬════════════╣
║ 178.6999999900 ║ 178.7000000000 ║ 178.7000000000 ║ 178.700000 ║
╚════════════════╩════════════════╩════════════════╩════════════╝
相关问题