hi
yeap...i think there is a problem with CF when rounding the value.
try this way if possible:
#round(100*250*.5053)#
I just discovered an error (with serious consequences) in my code. When I write #Round((0.5053*100) * 250)# I get 12632. But when I write #Round(50.53 * 250)# I get 12633. Which is of course rather surprising at first sight because mathematically both should have the same result. I suppose this has to do with the way decimal numbers are converted to floating point binary numbers. But it scares me because in my program these numbers are amounts of money and they should be correct. There are official rules in my company about how to calculate and round numbers (with euro ...
I just discovered an error (with serious consequences) in my code. When I write
#Round((0.5053*100) * 250)#
I get 12632. But when I write
#Round(50.53 * 250)#
I get 12633. Which is of course rather surprising at first sight because
mathematically both should have the same result. I suppose this has to do with
the way decimal numbers are converted to floating point binary numbers. But it
scares me because in my program these numbers are amounts of money and they
should be correct. There are official rules in my company about how to
calculate and round numbers (with euro and eurocents). The second result
(12633) is correct to me, but the problem is that the numbers 0.5053 and 250
(could be anything else) are coming directly from the database and that I must
multiply them first with 100 in my code (so I always get the wrong result).
It's worse: this kind of rounding happens many times on almost all of my pages.
How can I correct this situation or deal with it? Of course this error isn't
seen with every random number.
hi
yeap...i think there is a problem with CF when rounding the value.
try this way if possible:
#round(100*250*.5053)#
Thanks for the quick reply. This does return the correct result in this case,
with these numbers. But there can stil be cases where this doesn't work. Take
for example:
#Round(100 * 12.4737 * 50)#
This has the result 62368. But it should be 62369. So it's still not correct.
hi
I think by seeing all these things it better to do it manually like this.
<cFSET X="12345.3">
<cfif #val(mid(X,find(".",X)+1,len(x)))# gte 5 >
#round(x)#
<Cfelse>
#Int(x)#
</cfif>
try this with your requirements...if you still has the problem let post it
here...
Thanks, this indeed looks as a simple but correct alternative. Haven't tried it
out though because I tried a similar approach: instead of writing:
#Round( X * Y * Z)#
I now write:
#Round(Val(ToString(X * Y * Z)))#
Up until now this always gives the correct result. But thanks for your advice.
I'll post your answer in my archive also, so if my approach will show leaks in
a few days, I'll try yours. Thanks to you and to the forum. This was a great
help and i'm more assured now. Because I never write the Round() function
anywhere in my code pages. I created a ColdFusion function which does the
rounding for me. So simply adapting that function (which I placed in
Application.cfm) has solved all the rounding problems on all my pages (which
is a lot!) at once.
Lieven
Hmm... You accepted and is going to advertise absolutely incorrect solution...
The physics of this problem, as you partially mentioned yourself, is in
differences between an ideal math and the math with approximate numbers. In
your case, you are getting different results, because (0.5053*100) and 53.50
are DIFFERENT numbers (from computer's point of view, of course). Therefore,
you are rounding different numbers and getting [correct] different results.
Converting numbers to strings has very little to do with the real solution,
even it (amazingly) helps sometimes. And it helps, because when you do the
conversion, CF implicitly applies an internal default rounding algorithm
(different in different versions - and now Java version dependent). If you
want to be in control (you are counting money, as far as I understand), you
should not do this.
The correct approach would be applying your own rounding rules explicitly.
So, if 0.5053 is the number of euros and you want to get the number of cents
with the 2-decimal precision, you should:
<cfset cents=NumberFormat(0.5053 * 100, "____________.__")>
<cfset res=Round(cents*250)>
Also, it is a good idea to setup fields in your database as DECIMAL, not as
FLOAT or REAL.. Also, before inserting a value in the database, make sure you
have the right precision, otherwise CF again will "fireindy" round it for you.
And not necceseraly the way you expect.
Another common approach is to use integer math everywhere, where possible. If
your calculations go only up to whole cents, keep all numbers as integer cents,
not as floating point euros. If you need decimal places, use an appropriate
scale.
In your previous example:
<!--- Convert to integer --->
<cfset cents=Round(0.5053*1000)>
. . . . . . do some stuff on inetegers only. . . . . .
. . . . . . convert result back . . . . . .
<cfset result=NumberFormat(0.0001*result, . . . . . .>
P.S. Dollars behave similary
That is just a bug.
12632.5 shouldn't round to 12632 and you shouldn't have to go through all those girations to get it to round properly.
Hopefully MM will fix it.
Before reporting bug, just try this first:
<cfoutput>
#NumberFormat(0.5053*100, "___._______________________________")#
#Round((0.5053*100) * 250)#<br>
#NumberFormat(50.53, "___._______________________________")# #Round(50.53 *
250)#<br>
</cfoutput>
Bookmarks