Sunday, February 22, 2009

CF: Coldfusion and the perennial rounding bug

Through the years using any function that did implicit rounding in CF was not the safest thing to do. Many times when I thought this was resolved it came back with a vengeance to bite me in the you-know-what.
Thus, the safe route to use is to go through the database to round anything, unless you really do not have any choice.
This time it was the LSCurrencyFormat function which caused the headaches. It will round down at the .5 fraction rather than round up which is very annoying and disturbing at the same time. Here is a function specifically made for currency handling and it does not handle the basic calculations correctly.

Example code (comparing the round behavior against LSCurrency):

<cfloop from="0.001" to="0.009" step="0.001" index="fraction">

<cfset Amount = 1.10 + fraction>
<cfoutput>
number: #Amount# ls: #LSCurrencyFormat(Amount,'none')#
compare to rounded #Round(Amount *100)/100#
<BR>
</cfoutput>

</cfloop>


Unfortunately, I had flip back all the use of LSCurrencyFormat and pre-round the numbers via the database before passing them to this function. I do hope that Adobe does a little more testing on rounding for these in the future.

2 comments:

Duncan said...

I noticed a similar bug in DecimalFormat, years ago, and wrote a UDF to handle it:
http://www.cflib.org/udf/DecimalFormatCorrectly

Jamie Krug said...

I recently ran across a definite bug with the ColdFusion 8 round() function myself. I wrote a UDF as a workaround, which also allows you to round to a scale (decimal place, instead of just whole numbers). I blogged about it here.

As an alternative to going back to the database for rounding, you could always go straight to Java:

createObject('java', 'java.lang.Math').round()

Best,
Jamie