Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: Ray Camden

Did You Know That "000" Equals "00A" In ColdFusion?

By Ben Nadel on
Tags: ColdFusion

Dan Roberts just pointed out this very strange bug to me; apparently in ColdFusion the strings "0" (zero) and "A" are not equal unless they are preceded by zeros, in which case they are considered equal. I am sure this is a known bug, but I had never seen it, so I thought I would throw it out there.

To test this, I ran a bunch of comparison tests to see what worked and what failed:

  • <!--- Set the two strings for comparison. --->
  • <cfset strA = "00A" />
  • <cfset strB = "000" />
  •  
  •  
  • <p>
  • <cfif (strA EQ strB)>
  •  
  • #strA# EQ #strB#
  •  
  • <cfelse>
  •  
  • #strA# NEQ #strB#
  •  
  • </cfif>
  • </p>
  •  
  • <p>
  • <cfif (ToString( strA ) EQ ToString( strB ))>
  •  
  • #strA# EQ #strB# (Using CF ToString())
  •  
  • <cfelse>
  •  
  • #strA# NEQ #strB# (Using CF ToString())
  •  
  • </cfif>
  • </p>
  •  
  • <p>
  • <cfif (strA.ToString() EQ strB.ToString())>
  •  
  • #strA# EQ #strB# (Using Java ToString())
  •  
  • <cfelse>
  •  
  • #strA# NEQ #strB# (Using Java ToString())
  •  
  • </cfif>
  • </p>
  •  
  • <p>
  • <cfif strA.Equals( strB )>
  •  
  • #strA# EQ #strB# (using Java Equals())
  •  
  • <cfelse>
  •  
  • #strA# NEQ #strB# (using Java Equals())
  •  
  • </cfif>
  • </p>
  •  
  • <p>
  • <cfif NOT Compare( strA, strB )>
  •  
  • #strA# EQ #strB# (using Compare)
  •  
  • <cfelse>
  •  
  • #strA# NEQ #strB# (using Compare)
  •  
  • </cfif>
  • </p>
  •  
  • <p>
  • <cfif NOT strA.CompareTo( strB )>
  •  
  • #strA# EQ #strB# (using CompareTo())
  •  
  • <cfelse>
  •  
  • #strA# NEQ #strB# (using CompareTo())
  •  
  • </cfif>
  • </p>

None of these should come out as being equal, but running the above code gives us the following output:

00A EQ 000

00A EQ 000 (Using CF ToString())

00A EQ 000 (Using Java ToString())

00A NEQ 000 (using Java Equals())

00A NEQ 000 (using Compare)

00A NEQ 000 (using CompareTo())

As you can see, the standard ColdFusion "EQ" operator works on all string values (no matter how that string value was generated). But, all of the more "Java-oriented" and character-wise approaches truthfully tell the two strings apart. This doesn't seem to happen with anything but "0" and "A". Very strange.



Reader Comments

I submitted a bug report to Adobe not much earlier today.

Thanks for testing all of the equality functions/operators. I had to add some extra code to deal with this but will probably just switch it out with Compare() tomorrow.

Reply to this Comment

@Dan,

I would be curious to know how you even found this?!? Also as far as moving to the Compare() method... you probably want to move to CompareNoCase() as it is case-insensitive and the EQ operator is also case-insensitive.

Reply to this Comment

The company I work for manages a database of federal and states legislators. For some odd reason my boss decide way back when that the district field should have leading zeros, which he says makes it easier to eyeball problems. For example a district 1 is 001, a district A is 00A and officials without a district have 000. I was checking for district fields of 000 and of course ran into problems when records with 00A matched as well.

This came up a couple years ago but I just threw in a quick IsNumeric check which 00A fails on. That worked so I commented about the problem and moved on. Saw the comment today and thought it was about time I should bring it to their attention.

Reply to this Comment

The following link has some interesting information on the subject.

http://livedocs.adobe.com/coldfusion/7/htmldocs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=ColdFusion_Documentation&file=00000909.htm

Regarding the above problem it says:

"Short strings, such as 1a and 2P, can produce unexpected results. ColdFusion can interpret a single "a" as AM and a single "P" as PM. This can cause ColdFusion to interpret strings as date-time values in cases where this was not intended."

So coldfusion is comparing 0:00 AM to 0:00 AM.

Reply to this Comment

@Gary,

Nicely done! I guess this is ColdFusion's attempt to make things super easy for people to use (and at the same time, sacrificing a tiny bit of predictability). I certainly do love how easy it is to compare date/times in CF.

Reply to this Comment

Thanks Gary. That gives me some idea of what's probably going on.

Oddly though I can only get it to happen with EQ using 0 and 0A. Doesn't happen with 1 and 1A for example or 13 and 1P. GT and LT only compare like this if you include letters on both strings. Anyways, something to keep in mind.

Reply to this Comment

1 and 1a dont work because coldfusion turns the time into a fraction.

So for example the values

<cfset strA = "0.25" />
<cfset strB = "6A" />

would work. As strB is turned into 6:00 AM which is a quarter of a day (6/24 = 0.25).

Reply to this Comment

@Daniel:

Try "1p" EQ "13:"

Note the colon which, I guess, makes CF believe the string actually is the hour part of a time value.

Best,

Chris

Reply to this Comment

I recently had a somewhat similar problem with some floating point values in CF. I was comparing values from records in two different sets of SQL Server query results, values that when cfdumped to the screen were exactly the same, yet the EQ comparison always evaluated as false. I tried doing a javacast() of both values to double and comparing them, but the EQ still came back false. Again, cfdumping the returned values from javacast() seemed to confirm they were the exact same values. So I tried converting the values using DecimalFormat(). The EQ comparison correctly evaluated as true.

Reply to this Comment

Thought you guys might find it interesting to know the results of this code on Scorpio and BlueDragon (I have access to both). Scorpio is identical to CF 7, so they haven't 'fixed' this (yet). However, BlueDragon does it all correctly:
http://techfeed.net/000-00A.cfm

Reply to this Comment

We are lucky enough to have an ex-Adobe employee on our team, and he was able to get us a copy of Scorpio Beta. I wish I could share some of the new stuff they've got in there, but maybe it suffices to say that I'm very excited about the additions. And I'm not talking about all the boring Adobe product integration we've already heard about.

Reply to this Comment

I want to see if I can get a Beta. Apparently there is some program for it... time to do some snooping.

Reply to this Comment

You cannot use a SQL wild card when comparing values. However, you can use a regular expression and the REFind() function.

Take:

<cfif #variable# eq 'AE%'>

and make it into:

<cfif REFind( "^AE.+?", variable )>

The "^" means match at the beginning of the string.

AE is the literal string you are looking for.

.+? means at least ONE character after AE but don't bother checking more than one. You can probably remove this and JUST use "^AE", but it depends on what you want to do.

Regular expressions are totally awesome. If you want to know more about them, check out this primer:

http://www.bennadel.com/index.cfm?dax=blog:458.view

Reply to this Comment

Super old thread, but this obviously is still an issue (or intended to be this way???) :) I found this thread when searching for why CF was telling me that '14-0008' is equal to '14-8'. I would think that quotes around the string mean to read it as a string! Now I'm using CompareNoCase and it works great, just kind of odd behavior.

Thanks for sharing!

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.