This is an extremely common task: converting a Number to an int. There are a lot of ways to do it, but which is fastest in AS3? Today we’ll look at a performance test app that attempts to find the fastest way to accomplish this. The answer just may surprise you!

This is a (probably incomplete) list of ways to convert a converting a Number to an int:

  • The int(num) cast
  • The Math.floor function
  • Assignment to an int-typed variable
  • Left shift (<<) by 0
  • Right shift (>>) by 0
  • Bitwise AND (&) with 0xFFFFFFFF
  • Bitwise OR (|) with 0
  • Bitwise XOR (^) with 0
  • Two bitwise NOT (˜) operations

So I made a performance test app to try out all of the above conversion methods:

package
{
	import flash.display.*;
	import flash.utils.*;
	import flash.text.*;
 
	public class NumberToInt extends Sprite
	{
		private var __logger:TextField = new TextField();
		private function row(...cols): void
		{
			__logger.appendText(cols.join(",")+"\n");
		}
 
		public function NumberToInt()
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			__logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(__logger);
 
			init();
		}
 
		private function init(): void
		{
			var beforeTime:int;
			var afterTime:int;
			var i:int;
			var NUM:Number = 3.5;
			var REPS:int = 100000000;
			var valInt:int;
			var tempInt:int;
 
			row("Method", "Time");
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = NUM >> 0;
			}
			afterTime = getTimer();
			row(">>", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = NUM << 0;
			}
			afterTime = getTimer();
			row("<<", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = NUM & 0xFFFFFFFF;
			}
			afterTime = getTimer();
			row("&", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = NUM | 0;
			}
			afterTime = getTimer();
			row("|", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = NUM ^ 0;
			}
			afterTime = getTimer();
			row("^", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = ~(~NUM);
			}
			afterTime = getTimer();
			row("~~", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = (tempInt = NUM);
			}
			afterTime = getTimer();
			row("=", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = int(NUM);
			}
			afterTime = getTimer();
			row("int()", (afterTime-beforeTime), valInt);
 
			beforeTime = getTimer();
			for (i = 0; i < REPS; ++i)
			{
				valInt = Math.floor(NUM);
			}
			afterTime = getTimer();
			row("Math.floor()", (afterTime-beforeTime), valInt);
		}
	}
}

I ran this test app in the following environment:

  • Flex SDK (MXMLC) 4.6.0.23201, compiling in release mode (no debugging or verbose stack traces)
  • Release version of Flash Player 11.4.402.265
  • 2.3 Ghz Intel Core i7
  • Mac OS X 10.8.1

And here are the results I got:

Method Time
>> 188
<< 189
& 187
| 187
^ 187
~~ 217
= 278
int() 188
Math.floor() 538

Performance Graph

Surprisingly, to me at least, the simple int(num) cast is just as quick as the rest of the fast approaches. The other fast approaches are the single bitwise operations (shifts, AND, OR, XOR). Then comes assignment to an int-typed variable and the double bitwise NOT, which aren’t much slower. Bringing up the rear is Math.floor, which returns only a Number that has its fractional part chopped off and still requires conversion to a true int-typed variable.

The basic int(num) cast is, to me, the clearest code to read so it’s very nice to see that it doesn’t involve the performance costs of calling a global int function like, say, the global isNaN function. So for the best performance and clarity, keep it simple and use a cast.

Spot a bug? Have another way of converting that you think might be faster? Post a comment!