Faster isEven
A common programming task is to determine if an integer is even or odd. Recently, I saw an article showing how to do the task faster than the usual way: (i % 2) == 0
. Today’s article shows an even faster way to check for even or odd.
The usual way is simple and most people know it:
(i % 2) == 0
The way suggested by the article is much more complex:
((i * 0.5) - (i >> 1)) == 0
The way I’m proposing is both simple and, as you’ll see, even faster:
(i & 1) == 0
The way this works is to check only the singles digit. Here’s an alternate that works because only 0
is false
:
!(i & 1)
To find out which is the fastest, let’s put them through a little performance test:
package { import flash.display.*; import flash.utils.*; import flash.text.*; public class FasterIsEven extends Sprite { private var __logger:TextField = new TextField(); private function row(...cols): void { __logger.appendText(cols.join(",")+"\n"); } public function FasterIsEven() { 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 REPS:int = 1000000000; var even:Boolean; row("Method", "Time"); beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { even = (i % 2) == 0; } afterTime = getTimer(); row("(i % 2) == 0", (afterTime-beforeTime), even); beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { even = ((i * 0.5) - (i >> 1)) == 0; } afterTime = getTimer(); row("((i * 0.5) - (i >> 1)) == 0", (afterTime-beforeTime), even); beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { even = (i & 1) == 0; } afterTime = getTimer(); row("(i & 1) == 1", (afterTime-beforeTime), even); beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { even = !(i & 1); } afterTime = getTimer(); row("!(i & 1)", (afterTime-beforeTime), even); } } }
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.3.300.268
- 2.3 Ghz Intel Core i7
- Mac OS X 10.8.0
And here are the results I got:
Method | Time |
---|---|
(i % 2) == 0 | 10106 |
((i * 0.5) – (i >> 1)) == 0 | 2974 |
(i & 1) == 1 | 2277 |
!(i & 1) | 2612 |
We see some interesting results here:
- The naive method (
(i%2) == 0
) is the slowest by about 3x! - The method suggested in the article is much quicker
- My suggested method is the fastest by a decent margin
- My alternative method (
!(i & 1)
) is slower
So if you want a fast isEven
check, use my method: (i&1)==0
. It’s not complex and it’s quite a bit quicker than the usual approach. Also, you can make it into an isOdd
very easily: (i&1)==1
.
Spot a bug? Have a question or suggestion? Post a comment!
#1 by Volgogradetzzz on August 6th, 2012 ·
Wow. Really fast. I’ll put a link to your post if you don’t mind.
#2 by jackson on August 6th, 2012 ·
Feel free!
#3 by AlexG on August 6th, 2012 ·
I usually use i%2==0 but i&1==0 looks 5 times faster
#4 by Fernando on August 6th, 2012 ·
Hi there!
Thanks for putting those numbers together. I saw the same article you mentioned and I suggested the
(i & 1) == 1
test to the author. By the time, I had no time to check how much faster it would be (I thought that a bitwise operation would be faster, but I had no idea of how much faster).Checking your tests I see it is significantly faster, but I got surprised because
((i * 0.5) - (i >> 1)) == 0
is not so far behind. I thought that a multiplication, a subtraction and a shift operation combined would result in a much slower approach than a single bitwiseAND
Gut feeling exterminated by the numbers :)
#5 by jackson on August 6th, 2012 ·
Welcome to the crazy world of AS3 performance. :)
#6 by Fernando on August 6th, 2012 ·
haha Indeed!
#7 by focus on August 7th, 2012 ·
https://github.com/DmitriyYukhanov/Codestage-AS3-Framework/blob/master/src/ru/codestage/utils/NumUtil.as#L168
Wonder if comparing to 0 is even faster =) Method call kills any performance boost though, it’s more like memo for inline snippet)
#8 by jackson on August 7th, 2012 ·
Comparing to 0 gives you
isEven
. Comparing to 1 gives youisOdd
. I haven’t compared the performance of those, but I’d sure hope it’s close. :)#9 by deep on August 8th, 2012 ·
typo mistake (i & 1) == 1