Reputation: 2825
So I've come across a strange issue in SQL Server with rounding.
Here's my example:
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]
And here's the result I get:
+--------------+-------+--------+--------+
| amount | round | trim_1 | trim_2 |
+--------------+-------+--------+--------+
| 178.69999999 | 178.7 | 178.69 | 178.7 |
+--------------+-------+--------+--------+
The general idea here is that I'm trying to round by 6 decimal places, then trim/floor/truncate by 2 decimal places. This means that I'm expecting a result of 178.7
, but I'm getting a result of 178.69
for trim_1
(trim_2
is an alternative approach meant to yield the same result).
From what I can tell, I am using the round
function appropriately, as the SQL Server documentation states:
Syntax
ROUND ( numeric_expression , length [ ,function ] )
function
Is the type of operation to perform. function must be tinyint, smallint, or int. When function is omitted or has a value of 0 (default), numeric_expression is rounded. When a value other than 0 is specified, numeric_expression is truncated.
So I would expect trim_1
to match trim_2
.
Here's the kicker: if I pass the result of round
as a constant, and not as a variable, it works as expected:
select round(178.7, 2, 1) -- Yields 178.7
My guess is that SQL Server is doing something strange with floating points, or I've somehow managed to miss something. For what it's worth, I'm using SQL Server 2014, so perhaps that's my issue.
I'd like to get the result of trim_1
with as little code as possible, so that my end result looks cleaner.
Upvotes: 2
Views: 1376
Reputation: 953
Use decimal
instead of float
.
Taken from Float and Real (Transact-SQL)
Floating point data is approximate; therefore, not all values in the data type range can be represented exactly.
Replacing float
with decimal
in your code has the desired result:
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]
Results:
╔════════════════╦════════════════╦════════════════╦════════════╗ ║ amount ║ round ║ trim_1 ║ trim_2 ║ ╠════════════════╬════════════════╬════════════════╬════════════╣ ║ 178.6999999900 ║ 178.7000000000 ║ 178.7000000000 ║ 178.700000 ║ ╚════════════════╩════════════════╩════════════════╩════════════╝
Upvotes: 2