Translating this java implementation of Sieve of Eratosthenes? - java

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!

Related

Undoing bitwise operations

I have a Java function written by another programmer, which uses bitwise manipulation. I need a function that will undo the process (if possible). Perhaps some of you are more savvy than I with these operators. Here's what needs to be undone:
public void someFunc(int[] msg, int[] newMsg) {
int i = SOME_LENGTH_CONSTANT;
for (int j = 0; j < newMsg.length; j++) {
// msg[i] Shift left by 8 bits bitwise or with next msg[i+1]
// then bitwise not (~) and bitwise and with $FFF
newMsg[j] = (~(((msg[i] & 0x0f) << 8) | (msg[i + 1]))) & 0xfff;
i += 2;
}
}
I just wanted to try to do it, here is the results of my attempt.
In the beginning I split the expression into single operations:
int t1 = msg[i] & 0x0f;
Here is we lose all except for the last 4 bits.
int t2 = t1 << 8;
Clear low 8 bits by shifting t1.
int t3 = t2 | msg[i + 1];
Here we should understand if m[i + 1] is large than 255 (particularly m[i + 1] & 0xf00 > 0), we are not able to restore the low 4 bits of m[i] because they are irreversibly overwritten.
int t4 = ~t3;
Just a negation.
newMsg[j] = t4 & 0xfff;
Take low 12 bits.
Just did these steps in reverse order:
public static void someFuncRev(int[] msg, int[] newMsg) {
for (int i = 0; i < msg.length; ++i) {
newMsg[2 * i] = (~msg[i] >> 8) & 0xf; // take 11-8 bits
newMsg[2 * i + 1] = ~msg[i] & 0xff; // take 7-0 bits
}
}
I assumed SOME_LENGTH_CONSTANT == 0. It is easy to adjust the constant.
So, when the values inside msg are <=15, the function above recovers the initial sequence.
In case when the values are >15 and <=255, for msg[i] we can restore only 4 bits, msg[i + 1] are restored completely.
If the values are >255, we can't restore msg[i] because it was correpted by bits of msg[i + 1] (look above at the point no. 3); can restore 8 bits of msg[i + 1].
I hope this helps you.
My version, behold:
public void undoFunc(int[] newMsg, int[] original) {
int i = SOME_LENGTH_CONSTANT; // starting point
for (int j = 0; j < newMsg.length; j++) { // Iterate over newMsg
original[i] = ~((newMsg[j]&0xff00)>>8)&0x000f; // &0x000f to get rid of "mistakes" when NOT-ing
original[i+1] = (~(newMsg[j]&0x00ff)) & 0xff;
// i = initial value + 2 * j
i+=2;
}
}
What does your code do?
The input is an integer array. Every two values are used to create one value in the 'output' (newMsg) array.
First, it removes the left four bits of the first value in the input.
Then it "scrolls" that value 8 places to the left and puts zeroes in the empty spots.
It places the second value, msg[i+1], in the zeroes in the four rightmost bits.
It negates the value, all ones become zeroes and all zeroes become ones.
When 4) was done, the 4 leftmost bits (cleared in step 1)) become ones, so it undoes this with a &0x0FFF.
Example iteration:
msg[i] == 1010'1011
msg[i+1] == 0010'0100
1) 1010'1011 -> 0000'1011
2) 0000'1011 -> 0000'1011'0000'0000
3) 0000'1011'0000'0000 -> 0000'1011'0010'0100
4) 0000'1011'0010'0100 -> 1111'0100'1101'1011
5) 1111'0100'1101'1011 -> 0000'0100'1101'1011
newMsg[j] == 0000'0100'1101'1011 == 0x04DB (I think, from memory)
What my code does:
Getting the value of (what used to be) msg[i+1] is easy, it's the opposite/NOT of the rightmost 8 bits. Because negating it turns all leading zeroes into ones, I'll AND it with 0xff.
Getting the value of (what used to be) msg[i] was more difficult. First scrolled the leftmost 8 bits to the right. Then I negate the value. But the four unused/lost bits are now ones, and I expect that the OP wants these to be zeroes, so I &0x000f it.
NOTE: I used hexes with leading zeroes to make it more clear. These are not necessary.
NOTE: I divided the binary numbers into four bits for readability. So 0000'0100'1101'1011 is actually (0b)0000010011011011.
The values of msg[i+1] are recovered, but the leftmost four bits of msg[i] are lost.
Fwew.
Original Post:
In your code, you use &. What & does, is turn all 'agreeing bits' (when a bit from byte a and the equally significant bit from byte b are both 1) into 1s and the rest into 0s. This means that all bits that don't agree are, as #Mike Harris said, gone and destroyed.
Example & (and operation):
1010 & 0110 =
1 & 0 => 0
0 & 1 => 0
1 & 1 => 1
0 & 0 => 0
= 0010
As you see, only the second and third most significant bits (or zero-inclusive first and second least significant bit) of byte a are kept (bit #4/#0 is 'luck'), because they are 1s in byte b.
You can reverse all bits that are 1s in byte b in your code (one of which is fff, or 1111 1111 1111 in binary, though remember all bits more significant than the first one are removed, because 1111 1111 1111 == 000000000...00111111111111). But this won't reverse it, and only works depending on what the purpose of reversing it is.
More about the AND Bitwise operation on Wikipedia.

How to extract and display each of the four bytes of an integer individually as 8-bit values

edit: This question is not a duplicate. The whole point is to solve the question using masks and bit shifts.
I have a terrible programming teacher that introduces concepts without explaining them or providing material to understand them, and he's to arrogant and confrontational too seek help from.
So naturally, I'm stuck on yet another question without any guidance.
Given an integer variable x, write Java code to extract and display each of the four bytes of that integer individually as 8-bit values.
I'm supposed to use masking and bit shift operations to answer this question. I understand that masking means turning bits "on or off" and I understand that an integer has 32 bits or 4 bytes. But that information doesn't help me answer the question. I'm not necessarily asking for the entire solution, but any help would be appreciated.
Using masks and shifting to extract bytes from an integer variable i,
The bytes from most significant (highest) to least are:
byte b3 = (byte)((i>>24));
byte b2 = (byte)((i>>16)&255);
byte b1 = (byte)((i>>8)&255);
byte b0 = (byte)((i)&255);
out.println("The bytes are " + b3 + ", " + b2 + ", " + b1 + ", " + b0);
You could use a ByteBuffer
int myInt = 123;
byte[] bytes = ByteBuffer.allocate(4).putInt(myInt).array();
Then you can do whatever you want with it. If you want all bits you could do something like this:
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 8; j++)
{
if(bytes[i] & (1 << j))
{
System.out.print("1");
}
else
{
System.out.print("0");
}
}
System.out.print(" ");
}
I have not tested this code because I do not have Java on this PC, but if it does not work let me know. However this sould give you a ruff idea of what has to be done.
Firstly you have to understand bitwise operators and operations. ( https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html )
Boolean logic states that x & 1 = x and x & 0 = 0.
Knowing this we can create a mask for, lets say the least significant 4 bits of an 8 bit number: 11001101 & 00001111 = 1101 (205 & 0x0f = 13).
(we ignore the first 4 zeros and we got our 4 bits)
What if we need the most significant bits?
we apply the same idea, but now the mask will change, according to the bits we need: 11001101 & 11110000 = 11000000 (205 & 0xf0 = 192)
whoops... we got 4 zeros.
How can you get rid of that? Shifting to the right with 4 positions.
so 11000000 >> 4 = 1100 (most significant 4 bits)
I hope this example will help you to get a better understanding of bitwise operations.
One simple solution could be
bit0 = (x & 0xff000000) >> 24;
bit1 = (x & 0x00ff0000) >> 16;
bit2 = (x & 0x0000ff00) >> 8;
bit3 = (x & 0x000000ff);
(bit0 is MSB).
Masking isn't quite turning bits "on" or "off". It is a way to extract only the bits you want from the variable you are using. Lets say that you have the binary number 10011011 and you want the value of the rightmost 4 bits. To do this, you construct another binary number of the same length where there are 0's in the places that you don't want and 1's in the places that you do. Therefore, our binary number is 00001111. You then bitwise AND them together:
1 & 0 = 0
0 & 0 = 0
0 & 0 = 0
1 & 0 = 0
1 & 1 = 1
0 & 1 = 0
1 & 1 = 1
1 & 1 = 1
In java, using hex instead of binary since java doesn't have binary literals, this looks like
int result = 0x9B & 0x0F;
//result is 0xB (or 11 in decimal)
Bit shifting is just what it sounds like. If you have 10011111 and shift it right 2 bits you get 00100111. In java a bit shift of 2 looks like
int result = 0x9B >> 2;
For your program the idea is this:
Mask the rightmost byte of your integer
Shift integer right 8 bits
Repeat three more times

Understanding masking of Byte in 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.

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).

Obtain a specific subset of bits of an int in Java

How would I obtain a specific subset, say bits 5-10, of an int in Java?
Looking for a method where one can pass in specific bit positions. I'm not sure how I would create a mask that changes given the input, or even if that is how one should go about doing it.
I know this is how one would get the front say 10 bits of an int: (I think)
int x = num >> 22;
Say you have a number n, and want bits from i to j (i=5, j=10).
Note, that i=0 will give you the last bit
int value = n & (((1 << (j-i)) - 1) << i );
will give you the result.
The left part is obvious: you have a value, and you will put a bitmask on it.
The value of the mask is ((1 << (j-i)) - 1) << i. It says:
Take a 1 bit (value: 0000000000000001)
Shift it left j-i times (value: 2^(10-5) = 2^5 = 32 = 0000000000100000)
Deduct 1 (value: 31 = 0000000000011111) - have you seen the lowest bits reversed?
Shift it left i times (value: 31*32=992 = 0000001111100000)
So, you have got the bitmask for bits 5 - 10 (more precisely, from 5 to 9, since 10th is not included).
To obtain value of bit 1 (bits are indexed from 0 to 31)
int val = bits & 0x002;
To obtain value of bit 16
int val = bits & (1<<16);
To obtain value of bit n
int val = bits & (1<<n);

Categories

Resources