# Float vs Decimal?

• Does anyone have any opinions concerning the performance of Float vs decimal data types?

For example I have a table that stores balances, turnovers, and currency rates all of which were originally set up a float data types.

The types of operations I am performing on the data are arithmetic... (no comparisons that would require converting float values to numeric etc) mainly calculating currency balances... Because the table is small, (only about 100k records long & I would expect it to grow at a rate of about 10% annually) I'm guessing that converting to Decimal data types might not improve performance that much, if at all.

Does anyone have any thoughts about how significant an improvement I'd get?

• Performancewise, I wouldn't think much, if any. Accuracy wise however... Float's an inaccurate data type and prone to rounding errors. It's not something I'd like to store financial values in.

Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

We walk in the dark places no others will enter
We stand on the bridge and no one may pass
• My thoughts exactly - for performance it will probably be impossible to distinguish the two. However, you should not use FLOAT for financial values unless you are directing rounding errors into your retirement fund.

• Heh... Decimal is prone to more "rounding" errors than Float ever will be... it's a matter of rounding to the correct scale... For example, what should the answer to 1/3*3 be? Depending on the scale, it'll be some collection of 9's after the decimal point... With Float, it will more correctly be "1".

I know... extraordinary claims require extraordinary proof...

`DECLARE @a DECIMAL(3,0), @b-2 DECIMAL(18,0),@F FLOAT`

` SET @a = 3`

` SET @b-2 = 3`

` SET @F = 3`

`SELECT 1/@A*3.0, 1/@B*3.0,1/@F*3.0`

`SELECT 1/@A*3 , 1/@B*3 ,1/@F*3`

It's why the Money data type has 4 decimal places instead of 2... you should do all calculations with a higher scale than what you will display for the result. Your calculator works much the same way... if it displays 13 digits, it's doing it's calculations with 15 or more digits behind the scenes.

Now, which is faster... assuming that you want some accuracy to the nearest penny, let's use Money, DECIMAL(x,4), and FLOAT...

Here's the test data...

`DROP TABLE JBMTest`

`GO`

`--===== Create and populate a 1,000,000 row test table.`

` -- Column "RowNum" has a range of 1 to 1,000,000 unique numbers`

` -- Column "SomeMoney has a range of 0.0000 to 99.9999 non-unique numbers`

` -- Column "SomeDecimal has a range of 0.0000 to 99.9999 non-unique numbers`

` -- Column "SomeDecimal has a range of 0.0000 to 99.9999_ non-unique numbers`

` --Jeff Moden`

` SELECT TOP 1000000`

` SomeID = IDENTITY(INT,1,1),`

` SomeMoney = CAST(ABS(CHECKSUM(NEWID()))%10000 /100.0 AS MONEY),`

` SomeDecimal = CAST(ABS(CHECKSUM(NEWID()))%10000 /100.0 AS DECIMAL(19,4)),`

` SomeFloat = CAST(ABS(CHECKSUM(NEWID()))%10000 /100.0 AS FLOAT)`

` INTO dbo.JBMTest`

` FROM Master.dbo.SysColumns t1,`

` Master.dbo.SysColumns t2 --Lack of join criteria makes this a CROSS-JOIN`

`--===== A table is not properly formed unless a Primary Key has been assigned`

` -- Takes about 1 second to execute.`

` ALTER TABLE dbo.JBMTest`

` ADD PRIMARY KEY CLUSTERED (SomeID)`

` `

... and some code to test with...

`SET STATISTICS TIME ON`

` UPDATE dbo.JBMTest`

` SET SomeMoney = SomeMoney + 1.0`

` UPDATE dbo.JBMTest`

` SET SomeDecimal = SomeDecimal + 1.0`

` UPDATE dbo.JBMTest`

` SET SomeFloat = SomeFloat + 1.0`

`SET STATISTICS TIME OFF`

When writing to disk... decimal wins every time... but at the rate of about 300 milliseconds spread over a million rows. So, I say, who cares? Use what works best for you.

When doing memory calculations...

`DECLARE @BitBucketM MONEY`

`DECLARE @BitBucketD DECIMAL(19,4)`

`DECLARE @BitBucketF FLOAT`

`SET STATISTICS TIME ON`

` SELECT @BitBucketM = SomeMoney + 1.0`

` FROM dbo.JBMTest`

` SELECT @BitBucketD = SomeDecimal + 1.0`

` FROM dbo.JBMTest`

` SELECT @BitBucketF = SomeFloat + 1.0`

` FROM dbo.JBMTest`

`SET STATISTICS TIME OFF`

... Float wins but not by much over decimal. Consider again how small the difference is over a million rows.

Again, my recommendation is that you make money calculations out to at least 4 decimal places and do the correct rounding if needed.

--Jeff Moden

RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
First step towards the paradigm shift of writing Set Based code:
________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

Change is inevitable... Change for the better is not.

How to post code problems
How to Post Performance Problems
Create a Tally Function (fnTally)

• And... you might just want to learn to use Float for financial calculations and then round the answer to make the humans happy. A great many of the functions in SQL Server use Float as a returned datatype, so consider that you may be using Float even if you don't think so. 😉

--Jeff Moden

RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
First step towards the paradigm shift of writing Set Based code:
________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

Change is inevitable... Change for the better is not.

How to post code problems
How to Post Performance Problems
Create a Tally Function (fnTally)

• I kind of agree with what you are saying about decimal vs float for financial data... Actual financial data is stored seperately using the appropriate datatype. This table is used for calculating currency revaluations over a given period.

but what you say kind of raises an issue... (an exception that proves the rule.), and a better explanation of why I'm asking the question in the 1st place.

this table contains inputted data and calculated data... So for example I'm right with you that inputted turnovers etc should normally be stored as decimals... it is an exact record of what has been inputted after all. Now the problem starts to occur when we start calculating currency values...

If I am recording an exchange rate it makes sense to store it to 6dp. A decimal datatype looks an obvious choice. Now for business reasons I need to calculate an inverse rate as well...

So if I convert my \$10,000,000,000 to sterling using a direct rate and convert back using my inverse rate (as a decimal) I could get massive differences... if my inverse rate is stored to the same precision as the original rate.

The following code illustrates my point

declare

@dec as decimal(18,6),

@res as decimal(18,6),

@flo as float,

@dec2 as decimal(18,6)

set @dec = 1.909091

set @flo = 1/convert(FLOAT,@DEC)

set @res = 1/@dec

print @dec

print @flo

PRINT @RES

set @dec2 = 100000000 * @dec

print @dec2

set @dec2= 100000000/@RES

print @dec2

set @DEC2 = 100000000/@FLO

print @DEC2

Which is why the original data is stored as a float...

But I'd still feel more comfortable storing my data as a decimal (possibly giving my inverse rate a greater precision).

However if there's no trade of from improved performance using decimal then the cost of converting to a decimal of greater precision might prove significant. Any thoughts?

• sorry looks to me that Jeff has just made the point I'm trying to make. Thanks to all!

• You may want to "see" more here

By the way I work with financial data and we use "floats" 😉

* Noel

• Ben Leighton (6/24/2008)

sorry looks to me that Jeff has just made the point I'm trying to make. Thanks to all!

Absolutely not a problem, Ben. Thanks for the feedback.

--Jeff Moden

RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
First step towards the paradigm shift of writing Set Based code:
________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

Change is inevitable... Change for the better is not.

How to post code problems
How to Post Performance Problems
Create a Tally Function (fnTally)

• Rather than a question of decimal vs float, it's a question of scale and precision .... just ensure that the datatype you choose is sufficient for your purposes. I typically use money for stored values, decimals for calculations and interest/FX rates.

• I prefer fixed decimal for storing values because aggregating them produce perfect results. But while calculating (especially division), I cast to float, do the calc and convert back to fixed to store. Fixed is very important (for storage) in a double entry accounting system otherwise the entries will not balance. But float is very important for doing intermediate calculations because there is no fixed point processor (esp for division) but all cpus have floating point processors.

• also float is really fun to use for surrogate keys.

😉

---------------------------------------
elsasoft.org

• On more than one occasion, I've wished for a BCD data type like IBM uses on the AS/400 (iSeries now). Specify enough places, nad there's never a rounding issue. Of course, it works for IBM boxes because they put all the arithmetic operations in hardware to reduce the performance penalty associated with BCD.

• Having worked on a financial system in the early 90's where we were computing gain/loss per share per day it got quite interesting with the precision factor. In particular with some currencies.

What happened was that the "sum of the parts" (daily gain/loss) didn't equal the "whole" (net result) after a certain amount of time. The system was designed with a pre-specified number of decimal places using a DECIMAL datatype.

Fortunately, the underlying RDBMS was Oracle where we could just remove the scale factor by redefining the column's datatype to just an unqualified [Oracle's] NUMBER. This equated to DECIMAL(38,*). So it would store up to 38 digits in total with a "floating" number of decimal places. Analysis of the resulting gain/loss values showed that we needed at least 22 decimal places for some currencies.

For financial systems, accuracy is paramount.

So I'd use DECIMAL and enable the new VARDECIMAL option if space will be an issue.

See my related post:

http://www.sqlservercentral.com/Forums/Topic437894-1042-5.aspx#bm440631

[font="Arial Narrow"](PHB) I think we should build an SQL database. (Dilbert) What color do you want that database? (PHB) I think mauve has the most RAM.[/font]

• ....you KNOW you're supposed to do the multiplies FIRST, and then the divides... Regardless of the storage mechanism you're using, you're aritificially aggravating the amount of error.

Makes my blood run cold everytime I see that. Probably has something to do with my 3rd grade science teacher and that #\$%^&\$%# ruler. My knuckles still hurt when I think of that.....

----------------------------------------------------------------------------------
Your lack of planning does not constitute an emergency on my part...unless you're my manager...or a director and above...or a really loud-spoken end-user..All right - what was my emergency again?

Viewing 15 posts - 1 through 15 (of 30 total)