tags:

views:

1182

answers:

9
for (unsigned int i = 1; i <= 100; i++) {
    if (i & 0x00000001) {
        std::cout << i<<",";
    }
}

why does (and how): if( i & 0x00000001 ) figure out the odd number?

+20  A: 

It's using a bitwise "and" operator to mask off all but the last bit. If the last bit is a 1, the number is odd. Is that enough explanation?

Fred Larson
+1, I personally would also love to hear some explanation for using sesquipedalian notation instead of `1` ;-)
Michael Krelin - hacker
That was well said.
Jeremy Roberts
(To original poster) If you don't understand this Answer, which is correct, try changing 5 even numbers and 5 odd numbers to binary. Observe what happens on the last bit and how that relates to the number you transformed. (More specifically, look at what happens when the number is even and when the number is odd).Read up on bitwise AND as well
Malaxeur
@hacker: "Sesquipedalian" = "one who uses long words". Is that what you meant?
Michael Myers
so 0x00000001 is 8 bits, and int is 4 bytes which is 32 bits..so it still works..I can see if works, I was just not sure..
Tom
@Malaxeur - good idea, i'll do that
Tom
jprete
mmyers, sesquipedalian means foot and a half long, the word Horace used to refer to *long words themselves* — *sesquipedalia verba*. Incidentally, I also referred to notation which is approximately foot and a half long.
Michael Krelin - hacker
Malaxeur, nice scientific approach. Next step would to prove that all odd numbers are prime numbers as well. Just check it for 3, 5 and 7 ;-)
Michael Krelin - hacker
+13  A: 

When we look at numbers in base 10, it's easy to tell if a number is divisible by 10: it has a 0 in the last position. The code above looks at the digit in the last position as well, but in base 2. If it's non-zero, the number is not divisible by 2.

rlbond
+1 for not suggesting to try and check for a few numbers.
Michael Krelin - hacker
+10  A: 

It masks off the last bit. If you look at each place in the binary representation of a number (..., 256, 128, 64, 32, 16, 8, 4, 2, and 1), you'll notice that only the one's place is odd. All the rest of the places have an even value whether the bits are set or cleared (zero being even). And adding even numbers will always give an even number. Only that last one's place determines the parity of the number. The i & &0x00000001 part just isolates that last one's place.

Boojum
+2  A: 

You are doing bitwise comparison. The if bit0 AND bit0 are both 1, then the answer's bit0 = 1.

Seeing that &0x00000001 is 1, any numbers with this bit are odd.

0x00000001 = 1
0x00000010 = 2
0x00000011 = 3
etc.

So, if you do a bitwise AND

00000001 AND 
00000001 = 
00000001 (same as true)

00000010 AND 
00000001 = 
00000000 (same as false)

00000011 AND 
00000001 = 
00000001 (same as true)

etc
ericp
+20  A: 

0x00000001 is 1 in binary, although it's written in hexadecimal (base-16) notation. That's the 0x part.

& is the bit-wise 'AND' operator, which is used to do binary digit (bit) manipulations.

i & 1 converts all of the binary digits of i to zero, except for the last one.

It's straightforward to convert the resulting 1-bit number to a boolean, for evaluation by the if statement.

The following chart shows the last 16 binary digits of i, and what happens to them.

i:   i in binary:        i & 1 in binary:    convert to boolean
---- ------------------- ------------------- ---------------------
1    0000000000000001    0000000000000001    true
2    0000000000000010    0000000000000000    false
3    0000000000000011    0000000000000001    true
4    0000000000000100    0000000000000000    false
5    0000000000000101    0000000000000001    true
6    0000000000000110    0000000000000000    false
7    0000000000000111    0000000000000001    true
8    0000000000001000    0000000000000000    false
...  ...                 ...                 ...
99   0000000001100011    0000000000000001    true
100  0000000001100100    0000000000000000    false
system PAUSE
is this working only for integers, or does this work for floats too? it got me thinking, because floats are stored differently in memory, but using the modulo operator they are casted to ints, with bitwise `and` there is no cast.
knittl
You can't apply bitwise operators to floating-point numbers as they are represented in a platform-specific format and the most commonly-used format does not lend itself well to bitwise operations.
coppro
you can’t? so this will result in an compiler error? or just in unspecified behavior?
knittl
It will be unspecified behaviour. Feel free to post another question about finding odd numbers for floating-point types. :)
system PAUSE
@Fred, thanks for the fix. It was a copy-paste bug, and I didn't have any unit tests to verify it. :(
system PAUSE
+2  A: 

Odd numbers are all numbers of the form (2*n+1) where n is any integer (-2,-1,0,1....). So to find an odd number you have to see if the integer you're working with has that '+1' on it. When stored as an unsigned integer, a number can be expressed as the sum of powers of 2: 2^0 + 2^1 +2^2 + 2^4, etc. The binary version of the unsigned integer looks like a truth map of sorts: for every place there's a '1' in the binary number, add that power of two to the number. So, if you start at the right most digit in the binary representation of the unsigned integer and move left, each digit represents a power of two. If the digit is 1 then you add that power of two to the running sum and when you reach the end of the binary number.

Thus: 10001110b can be converted into an integer by summing the powers of two:

Rightmost: 2^1 + 2^2 + 2^3 + 2^7 :Leftmost = 141

The trick is that the rightmost digit represents 2^0. This is always 1. All the other digits represent even numbers. So, in terms of odd numbers you have to find the '+1'. That corresponds to the rightmost digit. All the other digits represent numbers of the form '2*n'. Therefore, to determine if a number of this format (unsigned integer) is odd you need only see if the right most bit is '1'.

The operation performed on the unsigned integer is a logical AND operation. Anything AND'd with 0 is 0, and 1 AND'd with 1 is 1. So the operation will cause all binary digits in the unsigned integer representation to be 0 except for the binary digit representing 2^0 (which is 1). So the unsigned integer binary representation will boil down to 0x00000001 if it's odd and 0x00000000 if it's even.

Note: When I write 0x00000000, the '0x' means that it's hexadecimal format. Each '0' represents four bits. So 0x00 is hexadecimal for 00000000b Written out in binary, the resulting possible unsigned integer binary representations after AND'ing the unsigned integer are:

00000000000000000000000000000000b == 0 and 00000000000000000000000000000001b == 1

Stephen Friederichs
+2  A: 

Before I say the following, I'll first say that I pretty much always use the bit test to determine whether an int is odd or even.

But, strictly speaking, you should use (i % 2) or ((i % 2) != 0) to determine is i is odd. This will work regardless of the represenation of negative numbers, while on a one's complement machine (-3 & 0x01) will return zero (a false result) even though clearly it's odd.

I realize that machiens that use something other than two's complement to represent negative number are very,very rare nowadays, but it's also true that compilers nowadays will universally compile (i % 2) to a bit test anyway. And remember, I usually don't follow my own advice here, so that's might be an indication of the true value of this suggestion.

Michael Burr
A: 

The bitwise AND operator follows this truth table for every bit:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Since computers work with numbers in base 2 and each bit represents a power of two value (1,2,4,8,16 ..),
the least significant bit represents the only odd number, regardless how big or small the value is, and regardless whether it is signed or unsigned. Since the resulting bit is only set if both operands have that bit set, the result is true if and only if the number is odd.

Example: 0b11101011 =
(1 * 2^0) + (1 * 2^1) + (0 * 2^2) + (1 * 2^3) +
(0 * 2^4) + (1 * 2^5) + (1 * 2^6) + (1 * 2^7) =
1 + 2 + 0 + 8 + 0 + 32 + 64 + 128 = 235
Without the least significant bit set, the value would be 234 and hence an even number.

Mads Elvheim
A: 

For Example how we make a Binary Equivalent

8 4 2 1

0 0 0 0 = 0

0 0 0 1 = 1

0 0 1 0 = 2

0 0 1 1 = 3

So you can see for any odd no. LSB is always set , Same you check :)

I hope my answer is clear

sat