0
DECLARE @TAX VARCHAR(30)=120.45
DECLARE @TaxRoundOf VARCHAR(30)
SET @TaxRoundOf=ROUND(@TAX,1)
SELECT @TaxRoundOf

This Gives Result (@TaxRoundOf=120.5)

DECLARE @TAX VARCHAR(30)=146.45
DECLARE @TaxRoundOf VARCHAR(30)
SET @TaxRoundOf=ROUND(@TAX,1)
SELECT @TaxRoundOf

This Gives Result (@TaxRoundOf=146.4)

But I need to return 146.50 . why this mismatch between two results? any one can help plz?

MatSnow
  • 7,357
  • 3
  • 19
  • 31
Vignesh D
  • 13
  • 5
  • 1
    it's quite evident that the round function is rounding down. You must use the proper function to round up instead. – James Jun 11 '18 at 08:05
  • 3
    Why are you using `VARCHAR`? If you were to store your numbers using a numeric data type, you would get the results you are expecting. – GarethD Jun 11 '18 at 08:06
  • Maybe he wants to concatenate that value to some string. – James Jun 11 '18 at 08:07
  • Convert to decimal or numeric and then apply round function. Should work – Mahesh Malpani Jun 11 '18 at 08:11
  • Why would you be rounding values with two decimal places (xxx.45) to a value with two decimal places but rounded to only 1 (xxx.50). That seems unusual. – Gordon Linoff Jun 11 '18 at 11:03

3 Answers3

2

Since you are using VARCHAR to store your numbers, SQL Server is having to do implicit conversion to float behind the scenes, which is having knock on effects on your calculations. You can reproduce this using the below query:

SELECT  ROUND(CONVERT(FLOAT, 120.45),1),            -- 120.5
        ROUND(CONVERT(FLOAT, 146.45),1),            -- 146.4
        ROUND(CONVERT(DECIMAL(10, 2), 120.45),1),   -- 120.50
        ROUND(CONVERT(DECIMAL(10, 2), 146.45),1)    -- 146.50

Since floating point numbers are not exact, 146.45 cannot be exactly represented as a float, and ends up being stored as a very slightly smaller number, so when this is passed to the round function, it is rounded down, instead of up.

The solution, as demonstrated by the 3rd and 4th columns in the above query, is to use a more precise data type.

GarethD
  • 68,045
  • 10
  • 83
  • 123
1

You can use this:

SET @TaxRoundOf=ROUND(10 * CAST(@TAX AS FLOAT)) / 10

instead of:

SET @TaxRoundOf=ROUND(@TAX,1)

DEMO

PS as @GarethD already mentioned I wouldn't use @TAX as VARCHAR type.

Andrei Suvorkov
  • 5,559
  • 5
  • 22
  • 48
0

You can also rely on numeric rounding instead of converting your string to a float, which can lose information.

Cast a string to numeric and then round:

select round(cast('146.45' as numeric(18,2)), 1)
-- 146.50

A decimal constant is already a decimal so there's no need to cast it:

select round(146.45, 1)
-- 146.50
jspcal
  • 50,847
  • 7
  • 72
  • 76