 # Strange Round behavious

I’ve got a weird rounding issue with Lucee 5.
To reproduce, paste this Code on trycf.com:

``````<cfscript>
price=4.1; discount=25;

result1 = price - (price*discount/100);				// 4.1 - 25% => 3.075
writeOutput('result1 => ' & result1 & '<hr />');	// outputs 3.075
resultRounded = Round(result1,2);					// this shoud round to 3.08
//resultRounded = NumberFormat(result1,'99999.99');	// workaound, but not nice!?
writeOutput('resultRounded (calculted) => ' & resultRounded & '<hr />');	// outputs 3.07 => wrong!

result2=3.075;
resultRounded2 = Round(result2,2);					// this should round to 3.08
writeOutput('resultRounded2 (fix) => ' & resultRounded2 & '<hr />');		// outputs 3.08 => correct!

dump(var=result1,label='result1');
dump(var=result2,label='result2');
if (result1 == result2) writeOutput('results are the same'); else writeoutput(result1 & ' and ' & result2 & ' are not equal!');
</cfscript>
``````

Explanation: a price is calculated; it should be 25% of 4.1 which will be 3.075.
The first output just shows the calculated price; 3.075 => correct.
Now, the result should be rounded mathematically to two decimals; result should be 3.08.
BUT => resultRounded outputs 3.07 => wrong!

If I directly set result=3.075 and then do the rounding to that result; output is 3.08 => correct!

Also take a look at the last 3 lines => a dump of both - result1 and result2 - shows both are numbers and both with 3.075. But a comparison of those outputs that they are NOT equal!

Is this a bug?

In the code you see a workaround; if I would use “NumberFormat” of result1 than it will output 3.08. But that’s not “nice”; and also resultRounded would be a string not a number (of course, I could change it to a number with Val(), but that’s definitely not what I want…)

This piece is probably doing 1.02499999… in Java. So it is a bug.
Workaround is round(price*discount/100,2)

Note: If you want compatibility with Adobe, you need to use numberFormat.

I’ve been using this UDF to round since 2008. (It was on a 2003 Macromedia blog entry by Christian Cantrell.) I just tested it and appears to work on Lucee 5 (at least on TryCF.com.)

``````function decimalRound(numberToRound){
var numberOfPlaces = 2;
var mode = "even";
var bd = createObject("java", "java.math.BigDecimal");
bd.init(arguments.numberToRound);
if (structCount(arguments) GTE 2 AND isNumeric(Arguments)){
numberOfPlaces = val(Arguments);
}
if (structCount(arguments) GTE 3 AND Listfindnocase("up,down", Arguments)){
mode = Arguments;
}
if (mode is "up"){
bd = bd.setScale(numberOfPlaces, bd.ROUND_HALF_UP);
} else if (mode is "down"){
bd = bd.setScale(numberOfPlaces, bd.ROUND_HALF_DOWN);
} else {
bd = bd.setScale(numberOfPlaces, bd.ROUND_HALF_EVEN);
}
return bd.toString();
}
``````

I looked at and tested the round() code and it isn’t that. I have a feeling it is just the Java code behind Lucee during the arithmetic. I haven’t tested if tag version makes a difference versus all cfscript.

Just ran on trycf as tag and it does the same thing. Specifically it is the “-” minus operation. I separated the multiplication and division part to it’s own variable and it still comes out wrong, even if using val() or numberFormat(). If I use numberFormat() or val() or the minus part it comes out correctly.

``````<cfset pdiscount = price*discount/100>
<cfset result1 = val(price-pdiscount)>
``````

I filed a bug for this issue.
https://luceeserver.atlassian.net/browse/LDEV-2778

1 Like