• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Possible comparison bug

Community Beginner ,
Jan 09, 2013 Jan 09, 2013

Copy link to clipboard

Copied

Hi all,

There's a good one, which may have an obvious answer (and that's the reason I first decided to ask it here before filing a bug).

<cfset t1 = ToString("00237000000075384887")>

<cfset t2 = ToString("00237000000075384892")>

<cfif t1 EQ t2><cfoutput>#t1# equal to #t2#</cfoutput><cfelse><cfoutput>#t1# different to #t2#</cfoutput></cfif>

The result of the above is rather surprising. Somewhat this sort of comparison thinks the numbers are equal. Also, even if both numbers are converted to strings,  ColdFusion still thinks they are equal.

If using Compare(t1,t2) however, ColdFusion starts comparing the strings as us, humans and distinguishes the difference between them

Now if there's any known limitation to comparing long numbers etc. or the fact that middle of each of them is filled with zeros affects it all, be welcome to point it out to me.

Simon

Views

905

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , Jan 09, 2013 Jan 09, 2013

Do some google on "floating point precision".

As CF is loosely typed, it has to make some guesses when it comes to doing operations in which type is significant. The EQ operator is an example of this: if CF can cast the operands to numerics, it will, which is what it's doing here. And when it casts those strings to numerics, both are 2.37000000075E+017, so they equal.

If you want to compare two strings explicitly as strings, then you need to use compare(), as you ahve already surmised.

There are no

...

Votes

Translate

Translate
LEGEND ,
Jan 09, 2013 Jan 09, 2013

Copy link to clipboard

Copied

Do some google on "floating point precision".

As CF is loosely typed, it has to make some guesses when it comes to doing operations in which type is significant. The EQ operator is an example of this: if CF can cast the operands to numerics, it will, which is what it's doing here. And when it casts those strings to numerics, both are 2.37000000075E+017, so they equal.

If you want to compare two strings explicitly as strings, then you need to use compare(), as you ahve already surmised.

There are no surprises in anything you're seeing though.

--

Adam

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Jan 09, 2013 Jan 09, 2013

Copy link to clipboard

Copied

You can use PrecisionEvaluate() to have CF store those numbers as BigDecimal instead of Double. You'll likely then see the behavior you expect.

Jason

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jan 09, 2013 Jan 09, 2013

Copy link to clipboard

Copied

Thanks guys!

@12Robots: tried PrecisionEvaluate(), though results were the same.

@Adam Cameron: Thanks for the explanation. Thought there's something there I've missed. Well, learned something new today

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 09, 2013 Jan 09, 2013

Copy link to clipboard

Copied

I would have expected precisionEvaluate() to work, but I can't coerce it into being helpful here.  But one can cut to the chase and just use BigDecimals:

<cfset t1 = createObject("java", "java.math.BigDecimal").init("00237000000075384887")>

<cfset t2 = createObject("java", "java.math.BigDecimal").init("00237000000075384892")>

<cfoutput>#t1.compareTo(t2)#<br /></cfoutput>

That works fine.

--

Adam

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Jan 10, 2013 Jan 10, 2013

Copy link to clipboard

Copied

LATEST

In this case, I think Adam is right that compare() is the right way to go.

As an aside precisionEvaluate() is a way of gettling Long numbers to be treated as accurate decimals instead of frustrating floating-point Doubles. But I believe precisionEvaluate() needs to occur at the time of comparison.

This code works for me in this situation. Though when testing with numbers that are closer in value I was getting inconsistent results, so it seems that some rounding is still occuring.

<cfset t1 = ToString("00237000000075384848")>

<cfset t2 = ToString("00237000000075384887")>

<cfif precisionEvaluate(t1) EQ precisionEvaluate(t2)><cfoutput>#t1# equal to #t2#</cfoutput><cfelse><cfoutput>#t1# different to #t2#</cfoutput></cfif>

Bottom line, if you want to compare them as strings, use compare(). If you want to be able to use EQ, mix some alpha characters in there

jason

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation