views:

694

answers:

18

given any number, what's the best way to determine it is even? how many methods can you think of, and what is the fastest way and clearest way?

+25  A: 
bool isEven = number % 2 == 0;
sipwiz
+1 nothing better
TStamper
modulo is slow. Use bit and. If the low bit is 1 then it is odd. If the low bit is 0 it is even.
Demi
bdonlan
Strilanc
Some compilers do this optimization, some don't. Don't trust your compiler when you can ensure this optimization yourself. If the number was the maximum integer value, the difference is speed can be quite significant.
Demi
Relying on a compiler optimization is bad practice. Modulo implies a division, which is mathematically more expensive. You should actually understand what your code is doing and write it in such a way that it clearly explains to any reader what you intended.
Jay
The OP doesn't specify a language, and not every language allows bit operations. Modulo isn't always available, but it can be readily written. Furthermore, if the bit ops aren't documented, it's not readily apparent to everyone what's going on, but I'd expect nearly all programmers could figure out a % 2 was testing for even/odd.
PTBNL
Chris Lutz
If you can't trust your compiler to optimize this, then you should get a new compiler. Strength reduction is one of the most basic optimizations.
Jay Conrod
@Jay Conrod - What if you're maintaining a legacy system with no other compilers?
Chris Lutz
A: 

You can either using integer division and divide it by two and inspect the remainder or use a modulus operator and mod it by two and inspect the remainder. The "fastest" way depends on the language, compiler, and other factors but I doubt there are many platforms for which there is a significant difference.

BobbyShaftoe
Many languages don't give you the remainder when doing integer division; I doubt this will ever be faster than straight modulo, as the compiler can always 'optimize' modulo to division-with-remainder
bdonlan
Right, that's why I said it depends on the language.
BobbyShaftoe
+29  A: 
bool isEven = ((number & 0x01) == 0)

The question said "any number", so one could either discard floats or handle them in another manner, perhaps by first scaling them up to an integral value first - watching out for overflow - i.e. change 2.1 to 21 (multiply by 10 and convert to int) and then test. It may be reasonable to assume, however, that by mentioning "any number" the person who posed the question is actually referring to integral values.

Demi
+1 for speed - but it is not nearly as clear
Shane C. Mason
In the selection between speed and clarity, especially in this unbounded case, I prefer speed.
Demi
@Shane: In all seriousness, I have seen (and used) the there's no 'clearest' for something as simple as this.
Dan Breslau
This is perfectly clear to me also - it should be clear from context what the code is doing - "bool isEven = " is pretty clear. And of course, you can always add a comment.
Blorgbeard
template<typename T>inline bool is_even( T number ){ return (number }a little clarity never hurt anyone
caspin
Agreed, this is very clear. When I saw this question with 8 answers I was anticipating this answer. As programmers, we should be able to interpret this sort of thing. We do want to make money.
TURBOxSPOOL
This is probably the answer the interviewer was looking for. A variation is "What's the most optimal way to tell if an integer is divisible by 4?" (Or pick some power of two)
Harvey
+4  A: 

Yes.. The fastest way is to check the 1 bit, because it is set for all odd numbers and unset for all even numbers..

Bitwise ANDs are pretty fast.

John Christman
+5  A: 

This is even easier in ruby:

isEven = number.even?
Blorgbeard
only Numeric-based (Numeric, Fixnum, Bignum) types. Not Decimal types
Demi
Wonder if a function lookup and call is faster on ruby than a logical and?
zaratustra
I doubt it, but I can't test this, because I get "-:1: undefined method `even?' for 1:Fixnum (NoMethodError)" when I try to run anything resembling this code.
Chris Lutz
For what it's worth (this is just guesswork), regardless of function lookup and call times, the function is probably implemented using the logical and trick (or with the modulus trick), so I seriously doubt it will be faster than either one of those.
Chris Lutz
I didn't say it was *faster* :P It works here: http://tryruby.hobix.com/ - try 1.even?
Blorgbeard
+4  A: 

If your type 'a' is an integral type, then we can define,

even :: Integral a => a -> Bool
even n =  n `rem` 2 == 0

according to the Haskell Prelude.

Don Stewart
this is equivalent to n % 2 in other languages isn't it?
David Johnstone
+7  A: 
isEven(n) = ((-1) ^ n) == 1

where ^ is the exponentiation/pow function of your language.

I didn't say it was fast or clear, but it has novelty value.

Oddthinking
+1 for a unique solution, although I don't know how practical it is.
musicfreak
+3  A: 

For floating points, of course within a reasonable bound.

modf(n/2.0, &intpart, &fracpart)
return fracpart == 0.0

With some other random math functions:

return gcd(n,2) == 2

return lcm(n,2) == n

return cos(n*pi) == 1.0
Unknown
+1  A: 

If it's low level check if the last (LSB) bit is 0 or 1 :)

0 = Even
1 = Odd

Otherwise, +1 @sipwiz: "bool isEven = number % 2 == 0;"

Hugo
+1  A: 

Assumming that you are dealing with an integer, the following will work:

if ((testnumber & -2)==testnumber) then testnumber is even.

basically, -2 in hex will be FFFE (for 16 bits) if the number is even, then anding with with -2 will leave it unchanged. ** Tom **

Tom
representation of negative integers can't be trusted inherently. One should refer to the language they are using. Your answer assumes "two's complement" representation. In "one's complement", -2 in hex is 0xFFFD, which would not give the correct answer. Another representation is "sign and magnitude", which, for 16 bits, would give 0x8002 - also an incorrect answer. Negative values are not as they would seem, oftentimes.
Demi
that noted, I'm giving you a vote for being tricksy.
Demi
Demi, your points are well taken, but the most common storage system is still 2's complement. The programmer in question is always responsible to know how data is stored in their environment.
Tom
+2  A: 

With reservations for limited stack space. ;) (Is this perhaps a candidate for tail calls?)

public static bool IsEven(int num) {
    if (num < 0)
        return !IsEven(-num - 1);

    if (num == 0)
        return true;

    return IsEven(-num);
}
Simon Svensson
you are clearly missing a case. How about including:if (num == 1) return false;
Demi
@Demi, IsEven(1) would return !IsEven(1-1) = !IsEven(0) = !true = false.
Simon Svensson
so true. my bad. point for you.
Demi
I don't think tail calls will work b/c the return values of IsEven need to be inverted (by the ! on the 2nd line). But I likes the solution.
Trey Jackson
+2  A: 

Actually I think (n % 2 == 0) is enough, which is easy to understand and most compilers will convert it to bit operations as well.

I compiled this program with gcc -O2 flag:

#include <stdio.h>

int main()
{
    volatile int x = 310;
    printf("%d\n", x % 2);
    return 0;
}

and the generated assembly code is

main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    movl    $310, 28(%esp)
    movl    28(%esp), %eax
    movl    $.LC0, (%esp)
    movl    %eax, %edx
    shrl    $31, %edx
    addl    %edx, %eax
    andl    $1, %eax
    subl    %edx, %eax
    movl    %eax, 4(%esp)
    call    printf
    xorl    %eax, %eax
    leave
    ret

which we can see that % 2 operation is already converted to the andl instruction.

ZelluX
I hate to beat a dead horse, but whether or not the optimization is done depends on what compiler you use. If yours does it, that's awesome. But what if mine doesn't?
Chris Lutz
+2  A: 

Similar to DeadHead's comment, but more efficient:

#include <limits.h>

bool isEven(int num)
{
    bool arr[UINT_MAX] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           // ...and so on
    };
    return arr[num];
}

As fast as an array index, which may or may not be faster than bitwise computations (it's difficult to test because I don't want to write the full version of this function). For what it's worth, that function above only has enough filled in to find even numbers up to 442, but would have to go to 4294967295 to work on my system.

Chris Lutz
+1 That is funny
Phil Hannent
the memory requirements for a version that works on INTEGER_MAX is going to cause most systems to grind to a halt...
Chii
+1  A: 

a % 2.

  1. It's clear
  2. It's fast on every decent compiler.

Everyone who cries "But! But! What if compiler doesn't optimize it" should find normal compiler, shut up and read about premature optimization, read again, read again.

A: 

Recursion!

function is_even (n number) returns boolean is
  if n = 0 then
     return true
  elsif n = 1 then
     return false
  elsif n < 0 then
     return is_even(n * -1)
  else
     return is_even(n - 2)
  end if
end
Jeffrey Kemp
making it work with non-integers is an exercise left to the reader...
Jeffrey Kemp
Seems like it'd work, stackoverflow issues aside ;)
Dominic Rodger
@Jeffrey - I guess you'd have to first define what made a non-integral number "even".
Dominic Rodger
I'd insert an additional "elsif" just before the final "else": "elsif n < 1 then return FILE_NOT_FOUND" :)
Jeffrey Kemp
-1 just noticed Svensson's answer...
Jeffrey Kemp
A: 

Continuing the spirit of "how many ways are there...":

function is_even (n positive_integer) returns boolean is
  i := 0
  j := 0
  loop
    if n = i then
       return (j = 0)
    end if;
    i := i + 1
    j := 1 - j
  end loop
end
Jeffrey Kemp
+5  A: 

The answer depends on the position being applied for. If you're applying for an Enterprise Architect position, then the following may be suitable:

First, you should create a proper Service-Oriented Architecture, as certainly the even-odd service won't be the only reusable component in your enterprise. An SOA consists of a service, interface, and service consumers. The service is function which can be invoked over the network. It exposes an interface contract and is typically registered with a Directory Service.

You can then create a Simple Object Access Protocol (SOAP) HTTP Web Service to expose your service.

Next, you should prevent clients from directly calling your Web Service. If you allow this, then you will end up with a mess of point-to-point communication, which is very hard to maintain. Clients should access the Web Service through an Enterprise Service Bus (ESB).

In addition to providing a standard plug-able architecture, additional components like service orchestration can occur on the bus.

Generally, writing a bespoke even/odd service should be avoided. You should write a Request for proposal (RFP), and get several vendors to show you their even/odd service. The vendor's product should be able to plug into your ESB, and also provide you with an Service level agreement (SLA).

brianegge
sorry, you've gone too far :) (I can hear the architects now... "you had me at SOA" ... )
Jeffrey Kemp
ROFLMAO!!!!!!!!!
Chii
A: 

In response to Chris Lutz, an array lookup is significantly slower than a BITWISE_AND operation. In an array lookup you're doing a memory lookup which will always be slower than a bitwise operation because of memory latency. This of course doesn't even factor in the problem of putting all possible int values into your array which has a memory complexity of O(2^n) where n is your bus size (8,16,32,64).

The odd/even property is only defined in integers. So any answer dealing with floating point is invalid. The abstract representation of this problem is Int -> bool (to use Haskell notation).

dharga