x&(x-1) ... why only 2's complement system?

L

Lax

Why is the "x&(x-1)" trick for removing the least significant set bit
from an integer only valid on 2's complement systems?
 
W

Walter Roberson

Lax said:
Why is the "x&(x-1)" trick for removing the least significant set bit
from an integer only valid on 2's complement systems?

Orders of Rear Admiral Grace Hopper.


Consider signed-magnitude and the number -2. 1 for the sign, a bunch
of binary 0s, then binary 10 at the end. x-1 is -3, which is
1 for the sign, a bunch of binary 0s, then binary 11 at the end.
Bitwise and the two together and you get 1 for the sign, a bunch of
binary 0s, then binary 10 at the end. Which is the representation of -2
which is the number you started with, so the technique does not work
for signed-magnitude.


With this example in mind, you should easily be able to determine
whether the technique works for 1's complement systems.
 
F

Falcon Kirtaran

Lax said:
Why is the "x&(x-1)" trick for removing the least significant set bit
from an integer only valid on 2's complement systems?

Because on a 2's compliment system (let's assume 8-bit for simplicity's
sake) x-1 is the same as x+(0b11111111) or x+0xFF. Let's say, for
example's sake, that x is 0b00101000 or positive 40. In that case,

0b00101000
+ 0b11111111
= 0b00100111 = 39

0b00101000
& 0b00100111
= 0b00100000 which is the correct answer.

However, this obviously relies on -1 being represented as the 2's
compliment of one (invert all bits and add one). If the system uses
some other method, it will be different and the bitmask will not be
equal to x-1. For instance, in a one's compliment system, x-1 is
represented as x+0b11111110.
 
L

Lax

Why is the "x&(x-1)" trick for removing the least significant set bit
from an integer only valid on 2's complement systems?

Thank you all (for suggesting and showing counterexamples).

So is this a good implementation-independent way of doing it?

(signed)( x & ( (unsigned)x-1 ) )
 
P

Peter Nilsson

Lax said:
Thank you all (for suggesting and showing
counterexamples).

So is this a good implementation-independent way of doing it?

(signed)( x & ( (unsigned)x-1 ) )

No, the right way is to make x unsigned to begin with, and
to forget about testing bits in negative integers.
 
F

Falcon Kirtaran

Eric said:
It is valid on all systems if `x' is non-negative.
That means, as a particularly useful special case, that
it is always valid if `x' is unsigned.

For negative values of `x', I suggest you take pencil
and paper and work through a few examples, using all three
of the representations C allows: two's complement, ones'
complement, and signed magnitude. To save some writing,
pretend your computer uses a narrow int of maybe six or
eight bits. Try a few different `x' values like -1, -2,
-10, and see what happens.

Hmm. I stand corrected.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top