SQL Server回合和截断问题

问题描述 投票:1回答:1

所以我在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  |
+--------------+-------+--------+--------+

这里的一般想法是我试图舍入6位小数,然后修剪/ floor / truncate 2位小数。这意味着我期待178.7的结果,但我得到178.69trim_1的结果(trim_2是另一种方法,意味着产生相同的结果)。

据我所知,我正在使用round函数,正如SQL Server documentation所述:

句法

ROUND ( numeric_expression , length [ ,function ] )  

功能

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

所以我希望trim_1能够匹配trim_2

这是踢球者:如果我将round的结果作为常量传递,而不是作为变量,它按预期工作:

select round(178.7, 2, 1) -- Yields 178.7

我的猜测是SQL Server正在用浮点做一些奇怪的事情,或者我已经设法错过了一些东西。对于它的价值,我正在使用SQL Server 2014,所以也许这就是我的问题。

我想用尽可能少的代码得到trim_1的结果,这样我的最终结果看起来更干净。

sql-server sql-server-2014 rounding
1个回答
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 ║
╚════════════════╩════════════════╩════════════════╩════════════╝
© www.soinside.com 2019 - 2024. All rights reserved.