Java: manipulate bits in a number - java

I was trying to implement a bit manipulation tool in Java.
I do not want to work with the Bitsetclass.
I am working with 64-bit Long values and implemented the following methods:
static final long toggle_bit(long number, int index) {
return (number ^= (1 << index));
}
static final long set_bit(long number, int index) {
return (number |= (1 << index));
}
static final long unset_bit(long number, int index) {
return (number &= ~(1 << index));
}
static final void print_bits(long number) {
String s = Long.toBinaryString(number);
String zeros = "0000000000000000000000000000000000000000000000000000000000000000"; //String of 64 zeros
s = zeros.substring(s.length()) + s;
System.out.println(s);
}
I think the best way of showing my problem is the result of this code:
>>> print_bits(set_bit(0L, 30));
0000000000000000000000000000000001000000000000000000000000000000
>>> print_bits(set_bit(0L, 31));
1111111111111111111111111111111110000000000000000000000000000000
I assume I am reaching negative values or something like that. I would
be very happy if someone could show me a very efficient way of
manipulating all 64 bits in a long-number.
Greetings,
Finn

Make index and the1 a long (declare as 1L) so that JVM doesn’t treat it as an integer.
I also have to note that in set_bits, |= (or equals) doesn’t account for when the bit is 1 but the desired value at the bit is 0

You are shifting an int value of 1. Try shifting a long value of 1, i.e. 1L << index

Related

Check partially known integer lies within a range

I have a peculiar problem for which I am looking for an efficient solution. I have a byte array which contains the most significant n bytes of an unsigned 4 byte integer (most sig byte first). The value of the remaining bytes (if any) are unknown. I need to check whether the partially known integer value could fall within a certain range (+ or - x) of a known integer. It's also valid for the integer represented by the byte array under test to wrap around.
I have a solution which works (below). The problem is that this solution performs way more comparisons than I believe is necessary and a whole load of comparisons will be duplicated in the scenario in which least sig bytes are unknown. I'm pretty sure it can be done more efficiently but can't figure out how. The scenario in which least significant bytes are unknown is an edge case so I might be able to live with it but it forms part of a system which needs to have low latency so if anyone could help with this that would be great.
Thanks in advance.
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
// partial integer byte array length guaranteed to be 1-4 so no checking necessary
static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange = false;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
// normal scenario, all bytes known
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
// we don't know least significant bytes, could have any value
// need to check if partially known int could lie in the range
int partialInteger = 0;
int mask = 0;
// build partial int and mask
for (int i = 0; i < partialIntegerBytes.length; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
// shift bytes to correct position
partialInteger |= (partialIntegerBytes[i] << shift);
// build up mask to mask off expected value for comparison
mask |= (0xFF << shift);
}
// check partial int falls in range
for (int i = -(range); i <= range; i++)
{
if (partialInteger == ((expectedValue + i) & mask))
{
inRange = true;
break;
}
}
}
return inRange;
}
EDIT: Thanks to the contributors below. Here is my new solution. Comments welcome.
static final int BYTES_IN_INT = 4;
static final int BYTE_SHIFT = 010;
static final int UBYTE_MASK = 0xFF;
static final long UINT_MASK = 0xFFFFFFFFl;
public static boolean checkPartialIntegerInRange(byte[] partialIntegerBytes, int expectedValue, int range)
{
boolean inRange;
if(partialIntegerBytes.length == BYTES_IN_INT)
{
inRange = Math.abs(ByteBuffer.wrap(partialIntegerBytes).getInt() - expectedValue) <= range;
}
else
{
int partialIntegerMin = 0;
int partialIntegerMax = 0;
for(int i=0; i < BYTES_IN_INT; i++)
{
int shift = ((BYTES_IN_INT - 1) - i) * BYTE_SHIFT;
if(i < partialIntegerBytes.length)
{
partialIntegerMin |= (((partialIntegerBytes[i] & UBYTE_MASK) << shift));
partialIntegerMax = partialIntegerMin;
}
else
{
partialIntegerMax |=(UBYTE_MASK << shift);
}
}
long partialMinUnsigned = partialIntegerMin & UINT_MASK;
long partialMaxUnsigned = partialIntegerMax & UINT_MASK;
long rangeMinUnsigned = (expectedValue - range) & UINT_MASK;
long rangeMaxUnsigned = (expectedValue + range) & UINT_MASK;
if(rangeMinUnsigned <= rangeMaxUnsigned)
{
inRange = partialMinUnsigned <= rangeMaxUnsigned && partialMaxUnsigned >= rangeMinUnsigned;
}
else
{
inRange = partialMinUnsigned <= rangeMaxUnsigned || partialMaxUnsigned >= rangeMinUnsigned;
}
}
return inRange;
}
Suppose you have one clockwise interval (x, y) and one normal interval (low, high) (each including their endpoints), determining whether they intersect can be done as (not tested):
if (x <= y) {
// (x, y) is a normal interval, use normal interval intersect
return low <= y && high >= x;
}
else {
// (x, y) wraps
return low <= y || high >= x;
}
To compare as unsigned integers, you can use longs (cast up with x & 0xffffffffL to counteract sign-extension) or Integer.compareUnsigned (in newer versions of Java) or, if you prefer you can add/subtract/xor both operands with Integer.MIN_VALUE.
Convert your unsigned bytes to an integer. Right-shift by 32-n (so your meaningful bytes are the min bytes). Right-shift your min/max integers by the same amount. If your shifted test value is equal to either shifted integer, it might be in the range. If it's between them, it's definitely in the range.
Presumably the sign bit on your integers is always zero (if not, just forcibly convert the negative to zero, since your test value can't be negative). But because that's only one bit, unless you were given all 32 bits as n, that shouldn't matter (it's not much of a problem in that special case).

Get the position of a bit and if it is set

I have a function which checks, whether a bit in an int is set or not.
But I think there will be a much faster implementation, since this one is linear and can't be the most efficient one, although I know the int should be between 1 and 1024.
public static int getBitPos(final int n) {
if (Integer.bitCount(n) != 1)
return Constants.UNDEFINED;
else {
for (int i = 0; i < Integer.MAX_VALUE; ++i) {
if (testBit(n, i))
return i;
}
}
return Constants.UNDEFINED;
}
Where testBit is the following standard function:
public static boolean testBit(final int n, final int pos) {
int mask = 1 << pos;
return (n & mask) == mask;
}
But there mast be a faster way, isn't there? If I have the value 17 and I want to know if the 4th bit (n = 8) is set? There should be a faster way to check whether the bit for n=8 is set...
Hope you can help me...
EDIT 1:
Thanks for the support. The comments and answers brought me to my mistake. I was setting the values wrongly, which made it more complicated than needed. I was never good at bit shifting.
I set the value like this, if I wanted the second bit to be set:
value = 2;
If I wanted the 4th bit to be set too, I added the value according to the 4th bit:
value += 8;
So value was 10, and the 2nd and 4th bit were set. So I saved the numbers in my class, instead of the bit-positions (8 as value, instead of 4 for the 4th bit, ...).
After changing this, I could get rid of my unnecessary function, which was way over the top!
Thanks for all help!
Your code always returns the lowest bit that is 1, if there is only one. You can achieve the same by doing this:
int foo = whatever;
int lowestSetBit = Integer.numberOfTrailingZeros(foo) + 1;
Your code would be
public static int getBitPos(final int n) {
if (Integer.bitCount(n) == 1)
return Integer.numberOfTrailingZeros(n) + 1;
return Constants.UNDEFINED;
}

Split Array Cells in Java

outp is of unsigned short* type. Some manipulations need to be done depending on the mode where mode is a global variable. In the if-block val is assigned to outp at the calculated index. In if-else block first the address pointed by outc is calculated and then the value is assigned at that location which in turn leads to change in a paricular cell of outp.
void lds_ld(int val, int x, int y, int value, unsigned short* outp)
{
unsigned char *outc;
if(mode==1)
{
outp[y*width +x] = val;
}
else if (mode==2)
{
outc = (unsigned char *)outp +y*width + x;
*outc= value;
}
else
{
printf("Wrong mode");
}
}
I need to write a java code that performs the same function. So i have written:
void lds_ld(int val, int x, int y, int value, int outp[])
{
short outc[];
if(mode==1)
{
outp[y*width +x] = val;
}
else if (mode==2)
{
//what to write here
}
else
{
System.out.printf("Wrong mode");
}
}
To write the if-else block i some how need to first split each array cell into two and then calculate the index and assign value at that index and then convert this array back to int[] type. whole How can i do this?
Mode 2 seems to allow you to only edit the first byte of the short, so you might try this:
int arrayValue = outp[y * width + x];
int firstByte = (arrayValue >> 8) & 0xFF;
int secondByte = arrayValue & 0xFF;
firstByte = value;
//if you want to edit the second byte:
//secondByte = value;
outp[y * width + x] = (int)(firstByte << 8) + secondByte;
There are no pointers in java, so you can either work on the same array and remember index to start from or create new array and copy part of source array to the target:
// check array size calculations: I am not sure I completely 
// your logic but I am sure you do.
int outc = new int[outp - (y*width + x)]; understand
System.arraycopy(outp, y*width + x, outc, 0, outc.length);
Depending on how width is set, you are
1) either setting two shorts from an int
2) or you are setting one half of a short, another short, and another half of a short from the int. Which halves of the shorts you are changing (most or least significant) will depend on your CPU architecture (and maybe your compiler)
Since (2) is quite painful, let's assume (1), i.e. width % 2 == 0. In Java, you have to split the int for yourself instead of assuming casting magic:
// determine the least significant 16 bits of your int
short lower = (short)(value & 0xffff);
// determine the most significant 16 bits of your int
short upper = (short)(value >>> 16);
// same calculation as in C-code, but for a short-array instead of for char-array
int pos = (y * width + x) / 2;
// assuming little endian order in your array (similar to running the C-code on x86
outp[pos] = lower;
outp[pos + 1] = upper;
For option (2) you need to split your int into three values:
byte left = (byte)(value & 0xff);
short middle = (short)(value >>> 8);
byte right = (byte)(value >> 24);
After doing so, you can assign middle directly to outp[pos], but you must combine the left and right bytes with the existing values in the cell using bit-manipulation-operations:
if ((y * width + x) % 2) != 0) {
// still assuming little endianness
outp[pos - 1] = (short)(outp[pos - 1] & 0xff00 | left);
outp[pos + 1] = (short)(((right << 8) & 0xff00) | (outp[pos + 1] & 0xff));
}
Another way of doing the given task would be using java.nio.ByteBuffer classes:
import java.nio.*;
// Wrap outp into a ByteBuffer
ByteBuffer outpBuf = ByteBuffer.wrap(outp);
outpBuf.putInt(y * width + x, value);
Please note that ByteBuffer is initially using Big Endian ordering, so you need to use outpBuf.order(ByteOrder.LITTLE_ENDIAN) to get results equivalent to the direct bit-operations suggested by the other posters.

BitSet to and from integer/long

If I have an integer that I'd like to perform bit manipulation on, how can I load it into a java.util.BitSet? How can I convert it back to an int or long? I'm not so concerned about the size of the BitSet -- it will always be 32 or 64 bits long. I'd just like to use the set(), clear(), nextSetBit(), and nextClearBit() methods rather than bitwise operators, but I can't find an easy way to initialize a bit set with a numeric type.
The following code creates a bit set from a long value and vice versa:
public class Bits {
public static BitSet convert(long value) {
BitSet bits = new BitSet();
int index = 0;
while (value != 0L) {
if (value % 2L != 0) {
bits.set(index);
}
++index;
value = value >>> 1;
}
return bits;
}
public static long convert(BitSet bits) {
long value = 0L;
for (int i = 0; i < bits.length(); ++i) {
value += bits.get(i) ? (1L << i) : 0L;
}
return value;
}
}
EDITED: Now both directions, #leftbrain: of cause, you are right
Add to finnw answer: there are also BitSet.valueOf(long[]) and BitSet.toLongArray(). So:
int n = 12345;
BitSet bs = BitSet.valueOf(new long[]{n});
long l = bs.toLongArray()[0];
Java 7 has BitSet.valueOf(byte[]) and BitSet.toByteArray()
If you are stuck with Java 6 or earlier, you can use BigInteger if it is not likely to be a performance bottleneck - it has getLowestSetBit, setBit and clearBit methods (the last two will create a new BigInteger instead of modifying in-place.)
To get a long back from a small BitSet in a 'streamy' way:
long l = bitSet.stream()
.takeWhile(i -> i < Long.SIZE)
.mapToLong(i -> 1L << i)
.reduce(0, (a, b) -> a | b);
Vice-versa:
BitSet bitSet = IntStream.range(0, Long.SIZE - 1)
.filter(i -> 0 != (l & 1L << i))
.collect(BitSet::new, BitSet::set, BitSet::or);
N.B.: Using BitSet::valueOf and BitSet::toLongArray is of course easier.
Pretty much straight from the documentation of nextSetBit
value=0;
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
value += (1 << i)
}
Isn't the public void set(int bit) method what your looking for?

A question in java.lang.Integer internal code

While looking in the code of the method:
Integer.toHexString
I found the following code :
public static String toHexString(int i) {
return toUnsignedString(i, 4);
}
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
The question is, in toUnsignedString, why we create a char arr of 32 chars?
32 characters is how much you need to represent an int in binary (base-2, shift of 1, used by toBinaryString).
It could be sized exactly, but I guess it has never made business sense to attempt that optimisation.
Because that method is also called by toBinaryString(), and an int is up to 32 digits in binary.
Because the max value for an int in Java is : 2^31 - 1

Categories

Resources