Understanding masking of Byte in Java - java

I was trying to save some space in a program and needed to use byte, I got on to a code that looks like this
private static final long MAX = 1000000000L;
private static final long SQRT_MAX = (long) Math.sqrt(MAX) + 1;
private static final int MEMORY_SIZE = (int) (MAX >> 4);
private static byte[] array = new byte[MEMORY_SIZE];
private void getbit(Long i)
{
byte block = array[(int) (i >> 4)];
byte mask = (byte) (1 << ((i >> 1) & 7));
return ((block & mask) != 0);
}
I cant understand what this means? In block why are we using i >> 4 should it not be i >> 3 since each byte is 8 bits? I also dont get what mask is doing?
I'm just getting started with byte's, any links to sources will be helpful
Here is some context - Source Code

Regarding the lowest 8 bits of 'i', this is what I can gather (where the MSB is bit 7 and the LSB is bit 0):
The value in the top 4 bits of 'i' represents an index to 'array'.
The value of 'block' is set to the value located at the above index in 'array'.
The value in bits 1-3 of 'i' represents a bit index to be masked out (the function will return true if the bit at that index in 'block' is 1).
Note: Bit 0 of 'i' seems to be unused.
I know that's not a specific answer, but I hope it helps to point you in the right direction.
I didn't look at the context source code though.

Related

Why does 11010100 << 1 equal 110101000, not 10101000?

Why when I try to shift bits for 110101002, the result is 1101010002, not 101010002.
int a = Integer.parseInt("11010100", 2) << 1;
I try to do this:
int a = (byte)(Integer.parseInt("11010100", 2) << 1);
But if the output value is greater than 128, everything goes into minus, which is logical.
How can I make that number of bits does not change?
Let's take it one step at a time.
Integer.parseInt("11010100", 2) - this is the int value 212. This is, by the way, needless; you can just write: 0b11010100.
0b11010100 << 1 is the same as 0b110101000, and is 424.
You then cast it to a byte: (byte)(0b11010100 << 1). The bits beyond the first 8 all get lopped off, which leaves 0b10101000, which is -88. Minus, yes, because in java bytes are signed.
You then silently cast this -88 back up to int, as you assign it to an int value. It remains -88, which means all the top bits are all 1s.
Hence, the final value is -88.
If you want to see 168 instead (which is the exact same bits, but shown unsigned instead of signed), the usual trick is to use & 0xFF, which sets all bits except the first 8 to 0, thus guaranteeing a positive number:
byte b = (byte) (0b11010100 << 1);
System.out.println(b); // -88. It is not possible to print 168 when printing a byte.
int asUnsigned = b & 0xFF;
System.out.println(asUnsigned); // 168.
// or in one go:
System.out.println(((byte) (0b11010100 << 1)) & 0xFF); // 168
If you want to set to 0 all bits higher than the bottom 8 bits, you can use bit-wise AND:
int a = (Integer.parseInt("11010100", 2) << 1) & 0xff;
System.out.println (Integer.toString(a,2));
Output:
10101000
Try something like this:
int anInt = Integer.parseInt("11010100", 2) << 1;
int asUnsignedInt= Byte.toUnsignedInt((byte) anInt);
toUnsignedInt has been introduced in Java SE 8.

Translating this java implementation of Sieve of Eratosthenes?

This is a program in Java which implements the Sieve or Eratosthenes by storing the array of booleans as an array of bits. I have never coded in Java before, but the general idea is easy to understand. However, I cannot understand how the getBit and setBit functions work? I am guessing that the getBit function creates a bitmask with the bit i set to 1 and does bitwise AND between the mask and the array? However, I'm not really understanding the details (eg. why i is right shifted by 4 before being passed as index to array, and why MEMORY_SIZE is equal to MAX right shifted by 4). Please explain the each step of getBit and setBit in words, and if possible an equivalent implementation in Python?
private static final long MAX = 1000000000L;
private static final long SQRT_MAX = (long) Math.sqrt(MAX) + 1;
private static final int MEMORY_SIZE = (int) (MAX >> 4);
private static byte[] array = new byte[MEMORY_SIZE];
//--//
for (long i = 3; i < SQRT_MAX; i += 2) {
if (!getBit(i)) {
long j = (i * i);
while (j < MAX) {
setBit(j);
j += (2 * i);
}
}
}
//--//
public static boolean getBit(long i) {
byte block = array[(int) (i >> 4)];
byte mask = (byte) (1 << ((i >> 1) & 7));
return ((block & mask) != 0);
}
public static void setBit(long i) {
int index = (int) (i >> 4);
byte block = array[index];
byte mask = (byte) (1 << ((i >> 1) & 7));
array[index] = (byte) (block | mask);
}
Some notes in advance:
(i >> 4) divides i by 16, which is the index of the block (of 8 bits) in array that contains the i-th bit
(i >> 1) divides i by 2
7 in binary code is 111
((i >> 1) & 7) means "the three rightmost bits of i / 2", which is a number between 0 and 7 (inclusive)
(1 << ((i >> 1) & 7)) is a bit shifted to the left between 0 and 7 times (00000001, 00000010, ..., 10000000). This is the bit mask to set/get the bit of interest from the selected block.
getBit(i) explained
First line selects the 8-bit-block (i.e. a byte) in which the bit of interest is located.
Second line calculates a bit mask with exactly one bit set. The position of the set bit is the same as the one of the bit of interest within the 8-bit-block.
Third line extracts the bit of interest using an bitwise AND, returning true if this bit is 1.
setBit(i) explained
Calculation of the 8-bit-block and the bit mask is equivalent to getBit
The difference is that a bitwise OR is used to set the bit of interest.
Edit
To your first question:
It almost makes sense now, can you please explain why we are able to find the position of the bit cooresponding to the number i by shifting a bit left ((i >> 1) & 7) times? In other words, i understand what the operation is doing, but why does this give us the correct bit position?
I think this is because of the optimized nature of the algorithm. Since i is incremented in steps of 2, it is sufficient to use half of the bits (since the others would be set anyway). Thus, i can be divided by 2 to calculate the number of necessary bit shifts.
Regarding your second question:
Also, just to clarify, the reason we increment j by 2*i after each call to setBit is because we only need to set the bits cooresponding to odd multiples of i, right?
Yes, because according to https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes:
Another refinement is to initially list odd numbers only, (3, 5, ..., n), and count in increments of 2p in step 3, thus marking only odd multiples of p.
Your algorithm starts with 3, increments i by 2, and counts in increments of 2*i.
I hope this helps!

bitwise right shift and 0xFF | Java

I am trying to understand a piece of code but not able to get clear idea about few points
here is the Java code
private String firstMethod(int number){
return secondMethod(number >> 16 & 0xFF, 0).concat(secondMethod(number >> 8 & 0xFF, 1)).concat(secondMethod(number & 0xFF, 7));
}
private static String secondMethod(int value, int offset)
{
return thirdMethod(value >> 4, offset).concat(thirdMethod(value & 0xF, offset + 4));
}
private static String thirdMethod(int value, int offset)
{
String chars = getAlphabet();
int pos = (value + offset) % 16;
return chars.substring(pos, pos + 1);
}
value passed to firstMethod is a random number for first time and all subsequent call to method will pass value incremented by 1.
I am clear about bit-wise right shift operation as well about the use of & 0xFF, however I am still not very clear about following points
Shifting given value by specific number (like 16 and 8 for first than no sift etc)
Not clear about use of offset ,specifically passing certain number as offset.
Can anyone help me to understand those 2 point
Shifting given value by specific number (like 16 and 8 for first than no sift etc)
You are printing bytes as hexi-decimal. Each byte is 8-bits so you want to shift each byte by
Not clear about use of offset ,specifically passing certain number as offset.
I am pretty sure the offset is either a) incorrect, b) a really obscure way of masking/encoding the data.
To print a number as a 6 byte hexi-decimal String you can do this.
System.out.println(String.format("%06x", 12345));
prints
003039
This is much shorter. ;)
>> has a surprising low precedence. This means
number >> 16 & 0xFF
is actually
number >> (16 & 0xFF)
or
number >> 16
what you indedn was
(number >> 16) & 0xFF
or as the result is unsigned.
(number >>> 16) & 0xFF
An integer is a 32-Bit Number.
So as a binary-number, you can represent number as:
XXXXXXXXAAAAAAAABBBBBBBBCCCCCCCC
(X, A, B, C stands for 0 or 1).
number >> 16 gives you XXXXXXXXAAAAAAAA.
number >> 16 & 0xFF gives you AAAAAAAA
By the firstMethod number is splited in 3 Bytes:
AAAAAAAA and BBBBBBBB and CCCCCCC (Shift of 16, shift of 8 and no shift)
and given to the secondMethod.
In the secondMethod the 8 Bits are splited in the higher four bits and the lower four bits.
In the thirdMethod the four Bits is translate to a String containing one char.
But the sense depends on "getAlphabet()".
Perhaps there will be also a usefull interpretation for the offset.
So you have to give further information!

How can I extract a particular bit in Java?

I need a specific bit in a byte value stored as int value. My code is as shown below.
private int getBitValue(int byteVal, int bitShift){
byteVal = byteVal << bitShift;
int bit = (int) (byteVal >>>7);
return bit;
}
It is working when I give the bitshift as 1 but when I give the bitshift as 2 and the byteVal as 67(01000011 in binary), I get the value of 'byteVal' as 268 while 'byteVal' should be 3(000011 in binary) after the first line in the method(the left shift). What am I doing wrong here?
For some reason when I try your code I don't get what you get. For your example, if you say byteVal = 0b01000011 and bitShift = 2, then this is what I get:
byteVal = 0b01000011 << 2 = 0b0100001100
bit = (int) (0b0100001100 >>> 7) = (int) (0b010) // redundant cast
returned value: 0b010 == 2
I believe what you intended to do was shift the bit you wanted to the leftmost position, and then shift it all the way to the right to get the bit. However, your code won't do that for a few reasons:
You need to shift left by (variable length - bitShift) to get the desired bit to the place you want. So in this case, what you really want is to shift byteVal left by 6 places, not 2.
int variables are 32 bits wide, not 8. (so you actually want to shift byteVal left by 30 places)
In addition, your question appears to be somewhat contradictory. You state you want a specific bit, yet your example implies you want the bitShift-th least significant bits.
An easier way of getting a specific bit might be to simply shift right as far as you need and then mask with 1: (also, you can't use return with void, but I'm assuming that was a typo)
private int getBitValue(int byteVal, int bitShift) {
byteVal = byteVal >> bitShift; // makes the bitShift-th bit the rightmost bit
// Assumes bit numbers are 0-based (i.e. original rightmost bit is the 0th bit)
return (int) (byteVal & 1) // AND the result with 1, which keeps only the rightmost bit
}
If you want the bitShift-th least significant bits, I believe something like this would work:
private int getNthLSBits(int byteVal, int numBits) {
return byteVal & ((1 << numBits) - 1);
// ((1 << numBits) - 1) gives you numBits ones
// i.e. if numBits = 3, (1 << numBits) - 1 == 0b111
// AND that with byteVal to get the numBits-th least significant bits
}
I'm curious why the answer should be 3 and I think we need more information on what the function should do.
Assuming you want the value of the byteVal's lowest bitShift bits, I'd do the following.
private int getBitValue(int byteVal, int bitShift){
int mask = 1 << bitShift; // mask = 1000.... (number of 0's = bitShift)
mask--; // mask = 000011111 (number of 1's = bitShift)
return (byteVal & mask);
}
At the very least, this function will return 1 for getBitValue(67, 1) and 3 for getBitValue(67,2).

Shifting 4 bits using a single number

I have to write a method that takes in an integer as a parameter (0, 1, 2, or 3). I have to use that to create a bitmask with a 0. So, if the parameter is 0, than the bitmask will be FFF0, for 1: FF0F, 2: F0FF, 3: 0FFF. I am trying not to hardcode it.
What I have tried, but it only works partially:
int bob = 0xFFFF;
int multi = 2;
multi = multi << param;
this works with 1 and 2, and for even those, it makes it 0xFF00, and 0xF000.
I am trying not to use multiplication either (that would make it a lot easier, so I don't want to use it).
Something like this:
bitmask = 0xFFFF;
bitmaskmask = 0xF;
bitmaskmask = bitmaskmask << parameter * 4;
bitmask = bitmask ^ bitmaskmask;
I would say:
0xFFFF - (0xF << (param * 4))
Given your inputs, you can achieve what you are looking for using the bitwise XOR operation as follows:
xorMask = 0x000F << (4*multi) ;
result = bob ^ xorMask ;
This creates an XOR mask with 1 bits in the appropriate portion of the 16 bit value, then XORing it with the input to 0 those bits in the output.

Categories

Resources