3

I am reading on some problems that are about optimization approaches.
In the problem how to sort numbers in a specific range the solution is to use a bitmap. And if a number can appear e.g. up to 10 times use to use half bytes to map the numbers and as counters to represent the number of occurences.
The concept I understand well. My problem is how to implement this in Java in a straightforward manner.

I am stuck on bit operations.
For example for the first part to increment the counter by 1, what I could think about was:

Locate the byte
E.g. bitValue[i]
Then do byte tmp = bitValue[i] & 0x0F to get the lower bits (if the counter is the low counter).
Then do tmp = tmp + 1 to increment by 1.
Then do bitValue[i] >> 2 to clear low end bits and then bitValue[i] <<2 to restore. Now we have the same high bits as the original and the low bits clear.
Then do bitValue[i] |= tmp to set low bits.
Now bitValue has the low bit counter incremented by 1. Right?

For the upper bit it would be the same process but for the upper bits.

Then when I have to check what is the number of the counter.

I thought to use bitmasks:
0x0 0x1 0x2 etc and use OR to check what is the current counter number.

All these seem to be too complicated. Am I on the right track? How are these operations addressed best in java coding?

Any input, guidance on this is highly welcome.

Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • Are you studying optimization or optimizing? If you're actually optimizing, have you identified a performance problem, or are you assuming that what you're doing is necessary? FWIW, it's probably not necessary. – Dave Apr 02 '12 at 20:51

1 Answers1

3

You're definitely on the right track. Here's some fleshed out code which increments the first four bits or second four bits of an int by a given amount.

Note that I use int here instead of byte. Even if your data is a byte it's usually much easier to work with it as an int. This is because java bitwise operators like | and & and << return int. So its easiest to work with your data as an int then cast back once you've done all your bit twiddling.

Also, if you need to deal with a large chunk of data (perhaps more than just the two counters you mention) on a per-bit level, you might consider taking a look at BitSet.

public class Test {
    public static void main(String[] args)
    {
        int counter = 0;

        // increment the low bits by 3 and high bits by 2
        counter = addLowBits( counter, 3 );
        counter = addHighBits( counter, 2 );

        // print the hex string to verify
        System.out.println( Integer.toHexString( counter ) );
        System.out.println( "Low Counter: " + ( counter & 0x0F ) );
        System.out.println( "High Counter: " + ( ( counter & 0xF0 ) >> 4 ) );
    }

    public static int addLowBits( int counter, int increment )
    {
        // get the low bits
        int low = counter & 0x0F;

        // increment by 1
        low = low + increment;

        // mask the high bits and insert new low bits
        counter = (counter & 0xF0) | low;

        return counter;
    }

    public static int addHighBits( int counter, int increment )
    {
        // now get high bits
        int high = ( counter & 0xF0 ) >> 4;

        // increment by 1
        high = high + increment;

        // mask the low bits and insert new high bits
        counter = (counter & 0x0F) | ( high << 4 );

        return counter;
    }
}
ulmangt
  • 5,343
  • 3
  • 23
  • 36
  • +1:Thank you for your example!!!Glad to know that I am not lost in this.And for checking on what is the counter number, the idea is to check each bitmask e.g. `0x1` `0x2` etc one by one, to see which is set, so as to know which nuber is in the counter? – Cratylus Apr 02 '12 at 20:04
  • `counter & 0x0F` gets you the value of the low bit counter and `(counter & 0xF0) >> 4` gets you the value of the high bit counter. Or are those not the numbers you're looking for? – ulmangt Apr 02 '12 at 20:08
  • The idea is that if I have `1` in the input the corresponding counter would be incremented by `1`.If `1` appears 4 times in the input data then the corresponding counter would have the value `4` (this is what the increment does, track occurences).Later when I want to know how many `1` appeared on input, I must somehow get number `4` from the counter. I.e. that `1` appeared `4` times.For this I thought to `AND` with each bitmask one by one. I.e. is `0x1`? is `0x2` in counter? is `0x3` in counter? is `0x4` in counter.Yes it is `0x4`.Is this the correct method? – Cratylus Apr 02 '12 at 20:12
  • I'm not sure what cycling through those bitmasks like you're suggesting accomplishes (unless I'm still misunderstanding what you're trying to accomplish). You don't need to try each binary value in turn. You can just grab the value for the counter (using the expressions from my last comment). If the low counter has been incremented four times, then the value of `counter & 0x0F` will be `0x4`. – ulmangt Apr 02 '12 at 20:16
  • `its easiest to work with your data as an int` Isn't this worse on code-readability though?E.g. it is not clear to someone reviewing the code that in my example I am actually interested in `bytes` and not `ints`.Or I am not thinking correctly about this? – Cratylus Apr 02 '12 at 20:27
  • That's true. Readability is a hard thing to judge though. I think having a bunch of `(byte)` casts everywhere makes the code ugly and less readable. But it does make it more explicit for sure. I'd say try writing your code both ways and see which way you like better. – ulmangt Apr 02 '12 at 20:37
  • I should also mention that if you're interested in dealing with a large chunk of data on a per-bit level, [BitSet](http://docs.oracle.com/javase/1.4.2/docs/api/java/util/BitSet.html) might be of interest to you. – ulmangt Apr 02 '12 at 20:41
  • One last point.I was concerned that may be the increment by 1 was "better" if I incremented using bitwise operations.Is this correct?And how could this be done? – Cratylus Apr 03 '12 at 15:36
  • Addition of primitive types (`int`/`short`/`byte`) is very fast. If you want to add 1 to an `int` value, I can't think of any reason not to use the `+` operator. – ulmangt Apr 03 '12 at 19:54