0

Could anyone explain the result of the following query? I think this is a bug in SQL Server 2014.

DECLARE @x float
SET @x=58.415
SELECT ROUND(58.415,2), ROUND(@x,2)

enter image description here

Dale K
  • 25,246
  • 15
  • 42
  • 71

2 Answers2

3

Because the first argument is stored as decimal(5,3):

EXEC sp_describe_first_result_set N'SELECT 58.415 x', null, 0;  

You have two different codes:

DECLARE @x float 
SET @x=58.415 
SELECT ROUND(58.415,2), ROUND(@x,2)

GO

DECLARE @x decimal(19,3)
SET @x=58.415 
SELECT ROUND(58.415,2), ROUND(@x,2)


GO

Basically, the float is

Approximate-number data types for use with floating point numeric data. Floating point data is approximate; therefore, not all values in the data type range can be represented exactly.

An improvement made by @Zohar explaining why the value is converted to decimal:

In Transact-SQL statements, a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary. For example, the constant 12.345 is converted into a numeric value with a precision of 5 and a scale of 3

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
gotqn
  • 42,737
  • 46
  • 157
  • 243
  • 1
    You might want to add a quote from [here:](https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver15#converting-decimal-and-numeric-data) *In Transact-SQL statements, a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary. For example, the constant 12.345 is converted into a numeric value with a precision of 5 and a scale of 3.* – Zohar Peled May 18 '20 at 06:19
  • 2
    I've edited to fix a couple of typos (including my name). Hope you don't mind :-) – Zohar Peled May 19 '20 at 09:16
1

The explanation for what you are seeing is that floating point arithmetic is not exact in SQL Server (or in any other database or programming language). Here is what is actually happening, with the "real" value being shown for explanation:

SELECT
    ROUND(58.415, 2),           -- rounds UP to 58.420, this is DECIMAL(10,3), EXACT
    ROUND(58.4149999999999, 2)  -- rounds DOWN to 58.41

The issue here is that when you made the following variable assignment:

DECLARE @x float
SET @x = 58.415

internally, SQL Server actually stored the value as an approximation, something like 58.41499999999. Then, when rounding to two decimal places, you were left with 58.41.

In general, if you require exact precision, you should use an exact type. In this case, DECIMAL(10,3) would work.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • While it's true that floating point arithmetic is not exact, that's not the reason here. gotqn's answer is the correct one in this case - see [here](https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver15#converting-decimal-and-numeric-data) – Zohar Peled May 18 '20 at 06:18
  • @ZoharPeled No, my answer is correct, other than I did not mention that the default literal is being treated as a decimal. But, this much is obvious from the behavior of the query. – Tim Biegeleisen May 18 '20 at 06:20
  • Actually, when I think about it, it's actually the combination of both yours and qotqn's answers that gives a complete and accurate explanation to this: You're correct about how SQL Server stores the float value `58.415`, while gotqn is correct about why it's stored accurately when using numeric literals... – Zohar Peled May 18 '20 at 06:29
  • @ZoharPeled Yeah...was just thinking that. Didn't know that decimal literals default to the `DECIMAL` type, but I guess that is also part of the correct explanation. – Tim Biegeleisen May 18 '20 at 06:29