I was looking at some code that outputs a number to the binary form with prepended 0s.
byte number = 48;
int i = 256; //max number * 2
while( (i >>= 1) > 0) {
System.out.print(((number & i) != 0 ? "1" : "0"));
}
and didn't understand what the i >>= 1 does. I know that i >> 1 shifts to the right by 1 bit but didn't understand what the = does and as far as I know, it is not possible to do a search for ">>=" to find out what it means.
i >>= 1 is just shorhand for i = i >> 1 in the same way that i += 4 is short for i = i + 4
EDIT: Specifically, those are both examples of compound assignment operators.
Related
This question already has answers here:
Round to the nearest power of two
(10 answers)
Closed 7 years ago.
there is a java code:
private static final int tableSizeFor(int c) {
int n = c - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : n + 1;
}
the result is: min(times of 2 and >=c)
for example, if c is 5,the result will be 8,if c is 16,the result will be 16.
I have calculated as the algorithm shows but I don't know how to understand this algorithm,anyone can explain this clearly,thanks.
This is looking for a power of two >= c.
It does this by filling in all the 1's below the top most 1. e.g. 101010 turns into 111111 and then adding 1 at the end to make it 1000000, ie. a power of 2.
It starts by subtracting 1 so that a power of two is left unchanged.
I am not sure why it checks for n >= Integer.MAX_VALUE as an int cannot be > than MAX_VALUE by definition. Perhaps this code was copied from an algo using long n originally.
Note where n > 1 << 30 this will over flow and produce 1 rather than MAX_VALUE.
I find confused with these expression while(n&3)==0 and n>>=2 . I am not sure when this condition is executed while((n&3)==0) and what happens n>>=2
public int numSquares(int n) {
while ((n & 3) == 0) //n % 4 == 0
n >>= 2;
if ((n & 7) == 7) return 4; //n% 8 == 7
if(is_square(n)) return 1;
int sqrt_n = (int) Math.sqrt(n);
for (int i = 1; i<= sqrt_n; i++){
if (is_square(n-i*i)) return 2;
}
return 3;
}
public boolean is_square(int n){
int temp = (int) Math.sqrt(n);
return temp * temp == n;
}
& is a binary AND operator. 3's representation in binary is 0000..0011. Therefore, the condition
(n & 3) == 0
is true when the last two bits of n are both set to zero. This happens when the number is divisible by 4, as suggested by the n % 4 == 0 comment.
Similarly, (n & 7) == 7 means "the last three bits of n are all set to 1", because the binary representation of 7 is 000..00111. Again, this is equivalent to having the remainder of 7 after dividing by 8, hence the n% 8 == 7 comment.
When you do n>>=2, you shift the number by two bits to the right, with sign extension. In your context it is equivalent to division by four, because the loop stops as soon as n is no longer divisible by four.
(n & 3) == 0 is an overly complex way of saying "n is a multiple of 4".
n>>=2 is an overly complex way of saying "divide n by 4, rounding down to the next lowest integer".
So this loop means "Keep dividing n by 4 until it's no longer a multiple of 4".
& is a bitwise AND
Bitwise operator works on bits in case of AND it return 1 only if both operands are 1, otherwise zero.
Suppose n = 4 in your case then
n & 3 would be 100 & 011 will give you 000 ie 0
>> bitshift operator
n >> 2 would be 100 >> 2 give you 001 ie 1
shifting each bit to the right 2 times.
You can read about the more in Docs
I want to implement a function to get the absolute value of a number in java: do nothing if it is positive, if it is negative, convert to positive.
I want to do this only using bit manipulations and no number comparators.
Please help
Well a negation:
-n
Is the same as the two's complement:
~n + 1
The problem is here you only want to negate if the value is < 0. You can find that out by using a logical shift to see if the MSB is set:
n >>> 31
A complement would be the same as an XOR with all 1's, something like (for a 4-bit integer):
~1010 == 1010 ^ 1111
And we can get a mask with the arithmetic right shift:
n >> 31
Absolute value says:
if n is < 0, negate it (take the complement and add 1 to it)
else, do nothing to it
So putting it together we can do the following:
static int abs(int n) {
return (n ^ (n >> 31)) + (n >>> 31);
}
Which computes:
if n is < 0, XOR it with all 1's and add 1 to it
else, XOR it with all 0's and add 0 to it
I'm not sure there's an easy way to do it without the addition. Addition involves any number of carries, even for a simple increment.
For example 2 + 1 has no carry:
10 + 1 == 11
But 47 + 1 has 4 carries:
101111 + 1 == 110000
Doing the add and carry with bitwise/bit shifts would basically just be a loop unroll and pointless.
(Edit!)
Just to be silly, here is an increment and carry:
static int abs(int n) {
int s = n >>> 31;
n ^= n >> 31;
int c;
do {
c = (n & s) << 1;
n ^= s;
} while((s = c) != 0);
return n;
}
The way it works is it flips the first bit, then keeps flipping until it finds a 0. So then the job is just to unroll the loop. The loop body can be represented by a somewhat ridiculous compound one-liner.
static int abs(int n) {
int s = n >>> 31;
n ^= n >> 31;
int c = (n & s) << 1;
c = ((n ^= s) & (s = c)) << 1; // repeat this line 30 more times
n ^= s;
return n;
}
So there's an abs using only bitwise and bit shifts.
These aren't faster than Math.abs. Math.abs just returns n < 0 ? -n : n which is trivial. And actually the loop unroll totally sucks in comparison. Just a curiosity I guess. Here's my benchmark:
Math.abs: 4.627323150634766ns
shift/xor/add abs: 6.729459762573242ns
loop abs: 12.028789520263672ns
unrolled abs: 32.47122764587402ns
bit hacks abs: 6.380939483642578ns
(The bit hacks abs is the non-patented one shown here which is basically the same idea as mine except a little harder to understand.)
you can turn a two's-compliment number positive or negative by taking it's logical negation
i = ~i; // i equals not i
You can use the Math.max() function to always get the positive
public static int abs(int i) {
return Math.max(i,~i);
}
This depends on what type of number you are using. For an int, use
int sign = i >> 31;
This gets the sign bit, which is 0 for positive numbers, and 1 for negative numbers. For other primitive types, replace 31 with the number of bits used for the primitive minus 1.
You can then use that sign in your if statement.
if (sign == 1)
i = ~i + 1;
I think you'll find that this little ditty is what you're looking for:
int abs(int v) {
int mask = v >> Integer.SIZE - 1;
return v + mask ^ mask;
}
It's based on Bit Twiddling Hacks absolute value equation and uses no comparison operations. If you aren't allowed to use addition, then (v ^ mask) - mask is an alternative. The value of this function is fairly questionable; since it's nearly as clear as the implementation of Math.abs and it's only marginally faster (at least on a i7):
v + mask ^ mask: 2.0844380704220384 abs/ns
(v ^ mask) - mask: 2.0819764093030244 abs/ns
Math.abs: 2.2636355843860656 abs/ns
Here's a test that proves that it works over the entire range of integers (the test runs in less than 2 minutes on an i7 processor under Java 7 update 51):
package test;
import org.hamcrest.core.Is;
import org.junit.Assert;
import org.junit.Test;
public class AbsTest {
#Test
public void test() {
long processedCount = 0L;
long numberOfIntegers = 1L << Integer.SIZE; //4294967296L
int value;
for (value = Integer.MIN_VALUE; processedCount < numberOfIntegers; value++) {
Assert.assertEquals((long) abs(value), (long) StrictMath.abs(value));
if (processedCount % 1_000_000L == 0L) {
System.out.print(".");
}
processedCount++;
}
System.out.println();
Assert.assertThat(processedCount, Is.is(numberOfIntegers));
Assert.assertThat(value - 1, Is.is(Integer.MAX_VALUE));
}
private static int abs(int v) {
int mask = v >> Integer.SIZE - 1;
return v + mask ^ mask;
}
}
This problem can be broken down into 2 simple steps:
1.
If >= 0 then just return the number.
2.
If smaller than 0 (ie. negative), then flip the first bit that indicates that the number is negative. This can easily be done with an XOR operation with -1 and the number; Then simply add +1 to deal with the offset (signed integers start at -1 not 0).
public static int absolute(int a) {
if (a >= 0) {
return a;
} else {
return (a ^ -1) + 1;
}
}
So I saw this one question on the interwebs that was along the lines of
Write a function that counts the number of bits in a character
Now obviously this confused me (or I wouldn't be here).
My very first thought was "aren't all chars 16 bits by default?" but obviously that has to be wrong because this question exists. I have no idea where to start. Maybe I can get the hex value of a char? Is there an easy way to convert from hex to binary or something? Is this something that can be asked about ANY language (I'm curious about Java here) or does it only matter to like C or something?
Here's another approach if you want to avoid recursion.
public static int bitsSet(char arg) {
int counter = 0;
for (int oneBit = 1; oneBit <= 0x8000; oneBit <<= 1) {
if ((arg & oneBit) > 0) {
counter++;
}
}
return counter;
}
Update
Here's a bit of an explanation. In the loop, oneBit bit-shifts to the left each time, which doubles its value. The <<= operation is a kind of shorthand for oneBit = oneBit << 1. So, the first time through, we have oneBit = 0000000000000001. Then the next time, we have oneBit = 0000000000000010, then oneBit = 0000000000000100, and so on, until we reach the last iteration, when we have oneBit = 1000000000000000 (these are all binary of course).
Now, the value of arg & oneBit will equal oneBit if arg has the matching bit set, or 0 otherwise. So the condition is executing counter++ if it encounters a set bit. By the time the loop has run all 16 times, we've counted all the set bits.
I'm assuming from your title that you're after the number of "set bits" (that is, bits that are equal to one). You can do it like this.
public static int bitsSet(char arg) {
return arg == 0 ? 0 : (arg & 1) + bitsSet((char)( arg >>> 1 ));
}
And yes, all chars in Java are 16 bits.
Update
Here's a bit of an explanation. (arg & 1) will check the rightmost bit of arg and return 0 or 1 depending on whether it is clear or set. So we want to take that 0 or 1, and add it to the number of set bits among the leftmost 15 bits. So to work that out, we shift arg to the right, introducing a zero at the left end. We need >>> rather than >> to make sure that we get a zero at the left end. Then we call bitsSet all over again, with the right-shifted value of arg.
But every time we do that, arg gets smaller, so eventually it's going to reach zero. When that happens, no more bits are set, so we can return 0.
To see the recursion working, take, for example, arg = '%' = 100101. Then we have the following - where all numbers shown are binary -
bitsSet(100101)
= (100101 & 1) + bitsSet(10010))
= (100101 & 1) + (10010 & 1) + bitsSet(1001)
= (100101 & 1) + (10010 & 1) + (1001 & 1) + bitsSet(100)
= (100101 & 1) + (10010 & 1) + (1001 & 1) + (100 & 1) + bitsSet(10)
= (100101 & 1) + (10010 & 1) + (1001 & 1) + (100 & 1) + (10 & 1) + bitsSet(1)
= (100101 & 1) + (10010 & 1) + (1001 & 1) + (100 & 1) + (10 & 1) + (1 & 1) + bitsSet(0)
= 1 + 0 + 1 + 0 + 0 + 1 + 0
= 3
All chars are 1-byte in C, Unicode (TCHAR) char's are 2 bytes.
To count the bits, you do bit shifting. I am not really that good at binary arithmetic personally.
According to Oracle JAVA doc for primitives.
char: The char data type is a single 16-bit Unicode character.
I need some explanation for this code.
This is the example code given by others.
for ( int i = 1; i <= 8; i++ )
{
if(check % 2 == 0)
sum += i;
else
sum -= i;
check /= 2; <--- Need explanation for this line.
}
But in the Pseudo code, there is no check /= 2; procedure.
Here is the full Pseudo code.
int binary = 0;
int sum;
while(binary<256)
sum = 0;
for(go through all 8 digits)
if the i-th digit is 0
sum += i
if the i-th digit is 1
sum -= i
end for
if sum == 0
output
binary++
end while
So, what is the purpose for that line of code?
Since sum, binary, and check is initialize as 0.
I have written this code using the Pseudocode given above.
But seems like my code will duplicate the output and one more problem, the format.
I want the output be like this format:
Enter a number : 3
-1 -2 +3 = 0
1 +2 -3 = 0
But my currently output is:
Enter a number : 3
-1 -2 3 = 0
1 2 -3 = 0
Here is my code:
CODE IS REMOVED!
Solved!
I'm too focus on the for-loop for the output part, hence miss the while-loop for the binary, because the pseudocode is for 256 possible solutions, hence, there will be same output for the front part, example:
1 - 2 - 3 + 4 = 0
1 - 2 - 3 + 4 + 5 - 6 - 7 + 8 = 0
Hence, the pseudocode may give an same output. So, since the solution is in 2 ^ n where n = 1, 2, 3, ... form, so change the
while( binary < 256 ) ---> while ( binary < Math.pow(2, input))
should solve it.
The format and the duplicate of the answer are solved.
This is the way to go through all digits. The most right digit is retrieved by check % 2, and after checking it, you shift check one digit (bit) to the right by check /= 2 (equals to check = check / 2;)
With this algorithm you are counting all the bit set to 1 and set to 0.
check /= 2;
it is like
check = check / 2;
and you can use it to shift all bits right by one.
For example:
(binary) 101 / (decimal) 2 = (binary) 10
that is 101 shift right by one digit.
Let's look at this line:
check /= 2;
In Java it is equivalent to the following simple statement:
check = check / 2;
Now let's find out the purpose behind it:
The right most digit is checked by check % 2
Then it is shifted right by one digit by check /= 2
check /= 2 is equivalent to check = check / 2;
its just a way of combining multiple assignments into a single one, like sum += 2 is equivalent to sum = sum + 2;