David
David

Reputation: 177

Bit Manipulation in Java - Conditionally Toggling Bits Based on Bit Values?

I have 8 Objects we will call "lights". Each light can be toggled on or off (0 or 1). Each light has an index (0-7).

I have no familiarity with Bitwise operations in Java, but I think the following code checks whether the light is on or off properly:

int value = 128;
int index = light.getIndex();
boolean lightIsOn = (value >> (index & 0x1) == 1);

I am currently facing the problem of not being able to turn on all of the lights. For example, if light 0 is on and I turn on light 1, light 1 will say it is on, but light 0 will then say it is off. That is with the following code:

if (!lightIsOn) {
   value = (value | 1 << index);
}

I know I am setting it improperly. I just can't figure out how to. This stuff doesn't exactly compute in my brain. I've read up on all of the Bitwise operators and it still doesn't really make sense to me. Can anyone please explain to me what I am doing wrong?

Upvotes: 2

Views: 188

Answers (3)

Scratte
Scratte

Reputation: 3166

I generally use debugging for this sort of thing. While it's great to just sort it out in one's head, sometimes it's nice to see the actual bitset. I commented out the intermediate debug statements, after I saw that it was working correctly:

public class StackOverflowTest {
  int value = 128;

  public static void main(String[] args){
    StackOverflowTest test = new StackOverflowTest();
    System.out.println(Integer.toBinaryString(test.value));
    System.out.println("is 7 on? " + test.lightIsOn(7));

    System.out.println("\n-- turnOff(7) --");
    test.turnOff(7);
    System.out.println("is 7 on? " + test.lightIsOn(7));
    System.out.println(Integer.toBinaryString(test.value));    

    System.out.println("\n-- turnOn(4) --");
    test.turnOn(4);
    System.out.println("is 4 on? " + test.lightIsOn(4));
    System.out.println(Integer.toBinaryString(test.value));
  }

  boolean lightIsOn(int index) {
//    System.out.println(Integer.toBinaryString(value));
//    System.out.println(Integer.toBinaryString(index & 0x1));
//    System.out.println(Integer.toBinaryString(value >> index));
//    System.out.println(Integer.toBinaryString((value >> index) & 0x1));
//    System.out.println(Integer.toBinaryString(value));
//    return value >> (index & 0x1) == 1; // this is not working
    return ((value >> index) & 0x1) == 1;
  }

  void turnOff(int index) {
    if (lightIsOn(index)) {
//      System.out.println(Integer.toBinaryString(value));
//      System.out.println(Integer.toBinaryString(1 << index));
//      System.out.println(Integer.toBinaryString(value));
      value = (value ^ (1 << index));
    }
  }

  void turnOn(int index) {
    if (!lightIsOn(index)) {
//      System.out.println(Integer.toBinaryString(value));
//      System.out.println(Integer.toBinaryString(1 << index));
//      System.out.println(Integer.toBinaryString(value));
      value = (value | (1 << index));
    }
  }
}

Upvotes: 2

erickson
erickson

Reputation: 269797

Your approach to "turning on the light" is okay.

You might think it is broken because there is a bug in how you test whether a "light" is on. Let's break it down:

boolean lightIsOn = (value >> (index & 0x1) == 1);

Starting with the innermost parentheses, you intersect index with 1. This results in shifting value one bit if the index is odd, and doing nothing if the index is even.

Then you compare the result of the shift with 1.

If value is 3 and index is zero, you get an erroneous false result. If value is greater than three, you get false regardless of index, which may be erroneous.

An expression like this will give intended results:

boolean lightIsOn = ((value >>> index) & 1) == 1;

Upvotes: 2

YouXiang-Wang
YouXiang-Wang

Reputation: 1127

Hope it may help you.

If your light number is less than 32.

You could try to use bit computing for each light. For example:

light1: 1
light2: 2
light3: 4
light4: 8
light5: 16
light6: 32
light7: 64
light8: 128

So If the mumber is 2: that will be light2
So If the mumber is 3: that will be light1 and light2
So If the mumber is 15: that will be light1,light2,light3,light4

Upvotes: 0

Related Questions