ActionScript 3 NaN: Not a No-brainer



In ActionScript 3, you can no longer assign null to specific native data types. If you try to do this with 'Number' for example you'll receive a warning that 'null used where Number type expected'. Take the following code snippet for example:

var MyNumber:Number;

MyNumber = getNumber();
if (MyNumber == null)
{
// do something
}

If you try to return 'null' from the getNumber() method you'll receive the aforementioned warning.

Although this is only a compiler warning, perhaps the better way to handle this is to have getNumber return NaN (and make the comparison against NaN) since in ActionScript 3 the default value of the Number data type is now 'NaN'(Not a Number). This leaves us with this:
var MyNumber:Number;

MyNumber = getNumber();
if (MyNumber == NaN)
{
// do something
}

But NaN is a funny kind of beast in ActionScript. If you tried to code things like they are above, you would receive another compiler warning, 'illogical comparison with NaN. This statement always returns false'. Any comparsion with NaN returns false in fact, suprisingly, even this one:
if (NaN == NaN)
{
}

Your best bet is to never deal with NaN directly but instead use the built in isNaN function to correctly evaluate whether your variable is not a number.
var MyNumber:Number;

MyNumber = getNumber();
if (isNaN(MyNumber))
{
// do something
}


16 comments :

Anonymous said...

For the record, NaN has the same behavior in AS2. You're right about not being able to return null where a function expects a number return type though. That's new.

HUWebDev said...

Thanks, Keith. I guess that in AS2 I had used null as the return type, so had never encountered this issue. Instead of returning null or NaN from such a method, perhaps a better design would be to throw an exception upon the discovery of the inability to return a valid number.

Unknown said...

The isNaN() method didn't work for me. I found the code below a good work around for the Number NaN problem.

var MyNumber:Number;

MyNumber = getNumber();
if (MyNumber != new Number(undefined))
{
// do something
}

Unknown said...

Neither of these solutions worked for me in Flex 2. There seems to be no function "isNaN" defined, and the other test didn't work either. So I wrote the following isNaN function - shown here with the isNumeric function that I was really after:

public function isNaN(number:Number):Boolean
{
return !(number <= 0 || number > 0);
}
public function isNumeric(string:String):Boolean
{
return !isNaN(Number(string));
}

Anonymous said...

Just for the record, there is an isNaN function in Flex 2(AS3). Please see the following URL:

http://www.adobe.com/livedocs/flex/2/langref/package.html

Anonymous said...

Number.NaN != Number.NaN

you can't compare NaN against NaN it's an illogical comparison. NaN == NaN will always evaluate to false;

John Berzy

FreeFormCoder said...

in order to make this function available in flex you have to:

import flash.display.Sprite;

:)

Subhash said...
This comment has been removed by the author.
Anonymous said...

I'm usually the last one to defend Adobe or ActionScript, I really think its a pretty broken language, but that being said -- NaN is pretty standard, and NaN != NaN is defined in the ISO floating point math standards.

Anonymous said...

yeah NaN == Nan returning false makes perfect sense, which is why I was so surprised when false == false didn't return false. Coming from the .NET world, I have been continually disappointed by ActionScript.

Anonymous said...

Hi, I was just looking for a predicate that could check if (and if only) a value was NaN, and I found a solution while reading this post : isNaN(myValue as Number).

Unless I'm mistaken, this evaluates to true only with NaN, (and false with null, undefined or an object).

Have a nice day...

Anonymous said...

Just what I was looking for. Thanks

Anonymous said...

Another NaN non brainer...never use a uint paramater with a defualt of NaN (as shown below)...because the paramater,x, in this case will ealuate to '0' and your if(isNaN(x)) will always fail since zero is a number...

AVOID this
function someFunc(x:uint=NaN){
if(isNan(x))
...
}


instead make x a "Number"...as below
function someFunc(x:Number=NaN){
if(isNan(x))
...
}


just spent a good hour trying to get to the bottom this issue and thought i'd share

Anonymous said...

Another NaN non brainer...never use a uint paramater with a defualt of NaN (as shown below)...because the paramater,x, in this case will ealuate to '0' and your if(isNaN(x)) will always fail since zero is a number...

AVOID this
function someFunc(x:uint=NaN){
if(isNan(x))
...
}


instead make x a "Number"...as below
function someFunc(x:Number=NaN){
if(isNan(x))
...
}


just spent a good hour trying to get to the bottom this issue and thought i'd share

Bruno Tachinardi said...

One of the simplest ways to check if the number is NaN is checking it against itslf:

function isNan(number : Number) : Boolean {
return !(number == number);
}

function isNumerical(number : Number) : Boolean {
return (number == number);
}

The trick is to take advantage of the comparison Nan == NaN that always return false

Anonymous said...

In case anyone else comes here looking for the same knowledge I did...I've found you can use this to compare numbers easily:

var num1:Number = NaN;
var num2:Number = NaN;

if(ObjectUtil.compare(num1, num2) == 0)
{
trace("Worked!");
}