因此,在四舍五入过程中,我遇到了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
的结果,以便最终结果看起来更简洁。
答案 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 ║ ╚════════════════╩════════════════╩════════════════╩════════════╝