View Full Version : odd and even numbers

ptmuldoon

11-16-2007, 03:51 PM

does php have any built in functions to determine if a number is odd or even? I came across the below when doing some google searches. But is that the simpliest way?

function is_odd($number) {

return $number & 1; // 0 = even, 1 = odd

}

I'm looking to create an if statement, and if the number is odd, do X, or if even, do Y.

johnnyb

11-16-2007, 04:04 PM

I'm not aware of such a function, but you could try this:

function is_odd($n) {

$test = $n/2; // divide the number you want to test by 2

if(strpos($test,'.') === false) { // if there's no decimal found in the result then the number must have been even.

return false; // so return false

} else { // otherwise we can assume the number is odd

return true; // so we return true

}

}

This is untested so make sure it works first!

Also, this assumes that a decimal point will be used after the whole numbers and before the part numbers, (like "2.5"). If your server is in a non-english language this may not be the case. For example a French PHP installation may return 5/2 = 2,5 in which case the function above would have to be modified.

aedrin

11-16-2007, 04:08 PM

Wow, that is a... weird solution.

function isOdd($n) {

return $n % 2;

}

marek_mar

11-16-2007, 04:19 PM

Ptmuldoons function is the best. Bitwise and is faster than modulo.

aedrin

11-16-2007, 04:22 PM

You're telling me that a division and a string search are faster than just a modulus operator (which is essentially a division)?

Not to mention that this is a common way of determining odd/even. I'm sure there's more inventive methods, but this is the easiest to read.

marek_mar

11-16-2007, 04:30 PM

I did say "ptmuldoon" not "johnnyb"...

rpgfan3233

11-16-2007, 04:50 PM

Bitwise is probably the fastest, but the compiler might simply optimize it to use bitwise given the situation:

function is_odd ($n) {

return ($n & 1);

}Why does it work? All it does is compare the bits in the ones place. If they are the same, the AND operation returns 1. Otherwise, it returns 0. Obviously if something is even, then the last bit would be 0 since binary is the base-2 system, which is even in itself. A quick table should help:

0 = 000 = even

1 = 001 = odd

2 = 010 = even

3 = 011 = odd

4 = 100 = even

5 = 101 = odd

6 = 110 = even

7 = 111 = odd

See? Every time the number is odd, the very last bit (the bit in the ones place) is 1. I won't get any more specific than this since it would go into the AND truth table and stuff.

An interesting thing to note, which may not be practiced much anymore: when you have $n % $m, where $m is a power of 2 (1, 2, 4, 8, 16, etc.), you can use $n & ($m - 1). Example:

$n = 40;

echo $n % 16, '<br />';

echo $n & 15; //16-1=15 obviouslySee? Same result, right? The only thing to note is that the '&' operator has lower precedence than ==, !=, etc., so if you have ($n & 1 != 1), for example, the result will be equal to $n & 0, which is 0. The right way to do it is to use (($n & 1) != 1). That way, $n & 1 gets evaluated first, instead of the 1 != 1. The difference is in the data type. If you need an explanation, just know that the comparison operators have a higher precedence than the bitwise operators - PHP: Operators - Operator Precedence (http://www.php.net/operators#language.operators.precedence)

johnnyb

11-16-2007, 05:13 PM

I never said that mine was fastest or best, just that it would probably work ;) Actually, I forgot about modulo - I never really use it.

The bitwise solution looks pretty nice to me.

aedrin

11-16-2007, 06:14 PM

I understand how the binary one works (I'd seen it before but never used so it hadn't 'stuck')

I did say "ptmuldoon" not "johnnyb"...

My visual compiler abstracted away the code in the original post, so I hadn't seen that he had posted that (or perhaps it was added afterwards since there was an edit). Hence I thought there was only mine and johnnyb's solution so I didn't think to look back up who you were talking about.

My bad.

vtjustinb

11-16-2007, 06:51 PM

Because of my old C days of bitflags I tend to use bitwise AND instead of MOD, but the question of what's fastest is kind of intriguing to me. Bitwise AND has the advantage of short-circuiting the evaluation if it runs into a 0, but I wonder if there's a bound where a really large number with all the bits on (like 1048575 which is 20 1s in binary) is actually less efficient than a small integer division (5 % 2)?

Just musing. :P

rpgfan3233

11-16-2007, 08:29 PM

Because of my old C days of bitflags I tend to use bitwise AND instead of MOD, but the question of what's fastest is kind of intriguing to me. Bitwise AND has the advantage of short-circuiting the evaluation if it runs into a 0, but I wonder if there's a bound where a really large number with all the bits on (like 1048575 which is 20 1s in binary) is actually less efficient than a small integer division (5 % 2)?

Just musing. :P

I'm not this old (thank goodness), but before there was a MOD instruction built into mainstream architectures, the bitwise AND existed as a short way of doing n MOD (2^m), but these days the speed difference is probably negligible, if there is a difference in the amount of time each takes.

Honestly, I think there may be. If all that MOD does is use the DIV or IDIV instruction, which returns the quotient in the EAX register and the remainder (result of a MOD operation) in the EDX register, and moves the remainder from EDX to EAX and calls it a new instruction, I wouldn't be surprised. However, that would mean that AND is much faster. DIV takes about 14 clocks on an 80386 processor, while AND only takes 2 clocks. I sure we have really come far enough to have closed that gap to a more negligible speed.

Back in those days, such a difference was probably a huge deal though. It is like creating a recursive function to calculate the 1024th Fibonacci number. It is much faster as an iterative function (loop) than as a recursive function (keep calling the function over and over and over until you get a stack overflow error like many people), not to mention how much less system intensive it is. I think that is why the bitwise AND trick became so widely adopted for a while, similar to how you can swap values with 3 bitwise XOR operations:

a ^= b;

b ^= a;

a ^= b;

Of course in C, you could just do a ^= b ^= a ^= b; :p

Of course, creating a temporary variable is usually fast enough these days, not to mention that those operations might not get translated directly as one might expect. That's probably why inline Assembly code exists. :)

aedrin

11-16-2007, 08:41 PM

similar to how you can swap values with 3 bitwise XOR operations:

That's one of those tricks that shouldn't really be used. Simply because it creates unreadable code.

I'm sure back then the difference in resources was worth it though.

vtjustinb

11-16-2007, 09:35 PM

That's one of those tricks that shouldn't really be used. Simply because it creates unreadable code.

I'm sure back then the difference in resources was worth it though.

Psht.. Code obfuscation is job security ;)

rpgfan3233

11-16-2007, 09:50 PM

Psht.. Code obfuscation is job security ;)

LOL I've heard that one before, and I love hearing it. :thumbsup:

moos3

11-16-2007, 10:45 PM

mod is the best way for that, I agree.

Powered by vBulletin® Version 4.2.2 Copyright © 2017 vBulletin Solutions, Inc. All rights reserved.