Why SOMETIMES … (String == Number) ….

March 10th, 2008 by Jaap Kooiker

So I encountered a really weird, but probably “explainable” problem in AS2 yesterday.
We all know that
trace("200.1" == 200.1) //true
and
trace("200.2" == 200.2) //true
trace(”200.3″ == 200.3) //true


trace(”200.81″ == 200.81) //true
trace(”200.81″ != 200.81) //false

This above works fine…but the following is what scares me the most….
trace("200.82" == 200.82) //false
Why the hell is the above false ???? And the really weird thing is
trace("200.82" != 200.82) //false
also false ???
So… it is NOT the same and it is NOT NOT the same?…wtf is it. AS doesn’t seem to know what it is.

Ok, bear with me a second. The following:

trace(”200.83″ == 200.83) //true
trace(”200.83″ != 200.83) //false

…that seems alright

At this point, I tried to make some sense of it and applied the following rules….
If a string has one decimal….it turns out to work fine…
If a string has two decimals….it only works fine if the last digit is uneven…

The next thing to check is a string with three decimals and…there seems to be a different stupid rule here…check…

trace("200.811" == 200.811) //true
trace(”200.811″ != 200.811) //false

trace(”200.812″ == 200.812) //true (should be false according to last “rules”)
trace(”200.812″ != 200.812) //false

Hmmm, it seems that we can erase the above rules from our head. It works fine at this point…what is that about?

One more sample…the second decimal after decimal point is an even digit.

trace("200.821" == 200.821) //false
trace(”200.821″ != 200.821) //false

trace(”200.822″ == 200.822) //false
trace(”200.822″ != 200.822) //false

Oh my god…..the second digit after decimal point is even and it is always false?? I can’t seem to make sense of it….sorry…
I can probably go on and on with more samples (four / five / etc. decimal digits) but the point is clear….it’s fucked.

If I trace typeof, it all seems to be a Number

trace(typeof(parseFloat(”200.81″))) //number
trace(typeof(parseFloat(”200.82″))) //number
trace(typeof(parseFloat(”200.821″))) //number

Converting the String to a Number or use parseFloat doesn’t work….so don’t bother trying.

Maybe it has something (the way it parses a string to a number or visa versa) to do with rounding Numbers…see what Arno has to say

Jaap

Posted in Actionscript 2.0, Bugs, Flash 8, Flash CS3, Flex |

6 Responses

  1. Josh Tynjala Says:

    ECMAScript does type conversion when you use == and !=, and that can lead to problems when you compare Numbers and Strings. I don’t know the full details on how type conversion, works, though, so I can’t explain why it works sometimes, but not all the time.

    Some tips:

    When you want to ensure that a String and a Number that may convert to the same value are considered non-equal because they’re different classes, use === and !== to compare them.

    When possible, use parseFloat() and parseInt() to convert your Strings to Numbers if you need numeric values. When using parseInt(), notice that there’s a second parameter that specifies the radix. You should ALWAYS specify this value (regular base-10 numbers should use 10 for the second parameter) because some numeric values don’t convert as you might normally expect.

  2. Josh Tynjala Says:

    Also, for some related tips on improving your AS code, check out the documentation for JSLint. It’s a JavaScript tool, but since both AS and JS come from the same language standard, many of the same rules apply.

    http://www.jslint.com/lint.html

  3. Derek Smalls Says:

    The trick is to keep adding equals signs until the problem goes away.

    trace(”200.821″ === 200.821) //false
    trace(”200.821″ !== 200.821) //true

    :P

  4. Jaap Kooiker Says:

    Thanx for the ideas. But still the problem isn’t solved. The thing I tried to do:
    I have one textfield and I want to compare the input of the textfield (wich is a string) to a number variable. The initial plan was to use parseFloat because I want to have point seperated numbers say 200.82. parseInt just makes it 200.
    I came up with the following…
    this.input_txt.text = “200.82″;
    trace(parseFloat(this.input_txt.text) == 200.82); // false

    this.input_txt.text = “200.81″;
    trace(parseFloat(this.input_txt.text) == 200.81); // true

    trace(typeof(parseFloat(this.input_txt.text))); // number

    Sure === doesn’t work because it compares classes wich will always be false in this case.

  5. borgfriend Says:

    did you try to convert both into Strings? that should do the trick

    var temp:Number = 200.82;
    trace(”200.82″ == temp.toString()) //true
    trace(”200.82″ != temp.toString()) //false

  6. Jaap Kooiker Says:

    @BorgFriend: It seemed to me there’s no other way indeed. I already was using your way (altough deep in my hart I don’t like it :P )….Thanx for your solution anyway..

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.