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 |
March 11th, 2008 at 1:10 am
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.
March 11th, 2008 at 1:12 am
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
March 11th, 2008 at 2:02 am
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
March 11th, 2008 at 8:28 am
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.
March 16th, 2008 at 1:25 pm
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
March 16th, 2008 at 7:57 pm
@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..