when
x = “12345.12345”
y = 12345.12345
ACF
(x eq y) is TRUE
(val(x) eq y) is TRUE
(x eq trim(y)) is TRUE
isNumeric(x) is TRUE
Lucee 5.1
(x eq y) is FALSE
(val(x) eq y) is TRUE
(x eq trim(y)) is TRUE
isNumeric(x) is TRUE
when
x = “12345.12345”
y = 12345.12345
ACF
(x eq y) is TRUE
(val(x) eq y) is TRUE
(x eq trim(y)) is TRUE
isNumeric(x) is TRUE
Lucee 5.1
(x eq y) is FALSE
(val(x) eq y) is TRUE
(x eq trim(y)) is TRUE
isNumeric(x) is TRUE
It’s a compatibility difference, I’ll grant you that, but I’m not sure I’d call it a bug, per se. It’s been this way since Railo and, strictly speaking, a string shouldn’t evaluate true with a number.
EDIT: The decimal point here causes the string version of the decimal number to be cast as a string, whereas the decimal number by itself is cast as a numeric. Though Micha or someone else involved in the Java can correct me if I’m wrong here, I’m pretty sure that’s what happening in this case.
ACF goes out of their way to make numbers and strings equivalent, If you know you’ll be comparing a string representation of a decimal number with an actual decimal number in Lucee, then I’d go with the second version of your tests:
val(x) eq y
since this works in both Lucee and ACF, if portability is a concern.
HTH
– Denny
FYI a bug and a testcase has been filed about this problem
https://luceeserver.atlassian.net/browse/LDEV-1419
Thanks Denny. I understand the issue, and can resolve. However cf is type-less so implementation should take this into account, especially for compatibility. And consistency as whole numbers work OK.
And this could lead to some quite difficult run-time anomalies for code moved from ACF.
I posted a bug on the issue tracker and they are thinking about what to do with it. At minimum need to be a searchable issue for portability concerns.
follow up
the comparison only failed if the the number’s length as a string was greater than 9
so
ie. 1234.56 eq “1234.56”
BUT
ie. 12345678.9 neq “12345678.9”
a fix has been made - see https://luceeserver.atlassian.net/browse/LDEV-1419
here is the diff…
if(Decision.isNumber(left)) {
if(left.length()>9) {
try{
return new BigDecimal(left).compareTo(new BigDecimal(right));
return new BigDecimal(left).compareTo(new BigDecimal(**Caster.toString(right)**));
}
catch(Throwable t) {ExceptionUtil.rethrowIfNecessary(t);}
catch(Exception e) {}
}
return compare(Caster.toDoubleValue(left,Double.NaN),right);
}