Big O of while loop - java

I have some code here that where x grows like big O(n), however I'm not sure why. It seems more of a logarithmic big O. Could I get some help figuring out why it grows like big O(n)? Thanks!
i = k; x = 1.0;
while (i > 1 ) {
i = (int) Math.floor( i / 2.0 );
x = x *2 ;

Complexity analysis has little to do with what value ends up in a variable, it a property of an algorithm, simplistically (for time complexity) how many steps it needs to do based on some input value.
In this case, given the input value k, your complexity is O(log N) because the division by two "halves the remaining solution space" on each iteration, along the lines of:
i = 128 64 32 16 8 4 2 1
The growth of the variable x which, as mentioned, has nothing to do with the algorithmic complexity, is to double each time through the loop.
So, you have a loop controlled by a value that halves on each iteration. And you have a variable that doubles on each iteration:
i = 128 64 32 16 8 4 2 1
x = 1 2 4 8 16 32 64 128
Hence it makes sense that the relationship between the input value and the final variable value will be a linear one, as shown by the equivalent Python code:
ctrl = 1024
other = 1
while ctrl > 0:
print('{0:4d} {1:4d}'.format(ctrl, other))
ctrl = ctrl // 2
other = other * 2
which outputs:
1024 1
512 2
256 4
128 8
64 16
32 32
16 64
8 128
4 256
2 512
1 1024
Note there that, though the final value in other is 1024, only ten "steps" were executed, since log21024 is 10.

If you're looking to optimize the problem, it looks like you're just calculating the largest bit
This can also be achieved a bit more efficiently with Integer.highestOneBit(int i)
Which is defined as
public static int highestOneBit(int i) {
// HD, Figure 3-1
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
return i - (i >>> 1);
}
and should be running in constant time (O(1)) since it is only bit operators
How it works is by shifting the bits down while ORing it with itself, causing all of the bits past the largest to become 1, then to isolate the largest it subtracts that number shifted over to remove all the trailing 1s

Related

Bitwise AND operator - Is it used to decrement previous bit interval?

I am not sure how to phrase the topic for this question because I am new to bit manipulation and really don't understand how it works.
I'm in the process of reverse engineering a game application just to see how it works and wanted to figure out how exactly the '&' operator is being used in a method.
Partial Code:
int n = (random numbers will be provided below)
int n2 = n & 1920 // interested in this line of code
switch (n2){
//ignore n2 value assignment inside of cases
case 256: {
n2 = 384;
break;
case 384: {
n2 = 512;
break;
case 512: {
n2 = 0
break;
Test Values:
Input Values | Output Values | Substituting Values
n = 387 | n2 = 384 | ( 387 & 1920 ) = 384
n = 513 | n2 = 512 | ( 513 & 1920 ) = 512
n = 12546 | n2 = 256 | ( 12546 & 1920 ) = 256
n = 18690 | n2 = 256 | ( 18690 & 1920 ) = 256
Based on this use case I have a few questions:
What is the & operator doing in this example?
To me it looks like most of the values are being rounded down to the nearest bit interval, except for the numbers greater than 10000
What is so important about the number 1920?
How did they come up with this number to get to a specific bit interval? (if possible to figure out)
The first thing you need to do, to understand bit manipulation, is to convert all base-10 decimal numbers into a number format showing bits, i.e. base-2 binary numbers or base-16 hexadecimal numbers (if you've learned to read those yet).
Bits are numbered from the right, starting at 0.
Decimal Hex Binary
256 = 0x100 = 0b1_0000_0000
384 = 0x180 = 0b1_1000_0000
512 = 0x200 = 0b10_0000_0000
1920 = 0x780 = 0b111_1000_0000
| | | | |
10 8 7 4 0 Bit Number
As you can see, n & 1920 will clear all but bits 7-10.
As long as n doesn't have any set bits above 10, i.e. greater than 0x7FF = 2047, the effect is as you stated, the values are being rounded down (truncated) to the nearest bit interval, i.e. multiple of 128.
128 + 256 + 512 + 1024 = 1920.
These are also powers of 2. let ^ be power of.
128 = 2^7
256 = 2^8
512 = 2^9
1024 = 2^10
The exponent also represents the location of the bit in the number, going from right to left starting with bit 0.
By ANDing the a value with 1920 you can see if any of the bits are set.
Let's say you wanted to see if n had only bit 7 was set.
if ((n & 1920) == 128) {
// it is set.
}
Or to see if it had bits 7 and 8 set.
if ((n & 1920) == 384) {
// then those bits are set.
}
You can also set a particular bit by using |.
n |= 128. Set's bit 7 to 1.

Is there a bit-wise trick for checking the divisibility of a number by 2 or 3?

I am looking for a bit-wise test equivalent to (num%2) == 0 || (num%3) == 0.
I can replace num%2 with num&1, but I'm still stuck with num%3 and with the logical-or.
This expression is also equivalent to (num%2)*(num%3) == 0, but I'm not sure how that helps.
Yes, though it's not very pretty, you can do something analogous to the old "sum all the decimal digits until you have only one left" trick to test if a number is divisible by 9, except in binary and with divisibility by 3. You can use the same principle for other numbers as well, but many combinations of base/divisor introduce annoying scaling factors so you're not just summing digits anymore.
Anyway, 16n-1 is divisible by 3, so you can use radix 16, that is, sum the nibbles. Then you're left with one nibble (well, 5 bits really), and you can just look that up. So for example in C# (slightly tested) edit: brute-force tested, definitely works
static bool IsMultipleOf3(uint x)
{
const uint lookuptable = 0x49249249;
uint t = (x & 0x0F0F0F0F) + ((x & 0xF0F0F0F0) >> 4);
t = (t & 0x00FF00FF) + ((t & 0xFF00FF00) >> 8);
t = (t & 0x000000FF) + ((t & 0x00FF0000) >> 16);
t = (t & 0xF) + ((t & 0xF0) >> 4);
return ((lookuptable >> (int)t) & 1) != 0;
}
The trick from my comment, x * 0xaaaaaaab <= 0x55555555, works through a modular multiplicative inverse trick. 0xaaaaaaab * 3 = 1 mod 232, which means that 0xaaaaaaab * x = x / 3 if and only if
x % 3 = 0. "if" because 0xaaaaaaab * 3 * y = y (because 1 * y = y), so if x is of the form
3 * y then it will map back to y. "only if" because no two inputs are mapped to the same output, so everything not divisible by 3 will map to something higher than the highest thing you can get by dividing anything by 3 (which is 0xFFFFFFFF / 3 = 0x55555555).
You can read more about this (including the more general form, which includes a rotation) in Division by Invariant Integers using Multiplication (T. Granlund and P. L. Montgomery).
You compiler may not know this trick. For example this:
uint32_t foo(uint32_t x)
{
return x % 3 == 0;
}
Becomes, on Clang 3.4.1 for x64,
movl %edi, %eax
movl $2863311531, %ecx # imm = 0xAAAAAAAB
imulq %rax, %rcx
shrq $33, %rcx
leal (%rcx,%rcx,2), %eax
cmpl %eax, %edi
sete %al
movzbl %al, %eax
ret
G++ 4.8:
mov eax, edi
mov edx, -1431655765
mul edx
shr edx
lea eax, [rdx+rdx*2]
cmp edi, eax
sete al
movzx eax, al
ret
What it should be:
imul eax, edi, 0xaaaaaaab
cmp eax, 0x55555555
setbe al
movzx eax, al
ret
I guess I'm a bit late to this party, but here's a slightly faster (and slightly prettier) solution than the one from harold:
bool is_multiple_of_3(std::uint32_t i)
{
i = (i & 0x0000FFFF) + (i >> 16);
i = (i & 0x00FF) + (i >> 8);
i = (i & 0x0F) + (i >> 4);
i = (i & 0x3) + (i >> 2);
const std::uint32_t lookuptable = 0x49249249;
return ((lookuptable >> i) & 1) != 0;
}
It's C++11, but that doesn't really matter for this piece of code. It's also brute-force tested for 32-bit unsigned ints. It saves you at least one bit-fiddling op for each of the first four steps. It also scales beautifully to 64 bits - only one additional step needed at the beginning.
The last two lines are obviously and shamelessly taken from harold's solution (nice one, I wouldn't have done that so elegantly).
Possible further optimizations:
The & ops in the first two steps will be optimized away by just using the lower-half registers on architectures that have them (x86, for example).
The largest possible output from the third step is 60, and from the fourth step it's 15 (when the function argument is 0xFFFFFFFF). Given that, we can eliminate the fourth step, use a 64-bit lookuptable and shift directly into that following the third step. This turns out to be a bad idea for Visual C++ 2013 in 32-bit mode, as the right shift turns into a non-inline call to code that does a lot of tests and jumps. However, it should be a good idea if 64-bit registers are natively available.
The point above needs to be reevaluated if the function is modified to take a 64-bit argument. The maximum outputs from the last two steps (which will be steps 4 and 5 after adding one step at the beginning) will be 75 and 21 respectively, which means we can no longer eliminate the last step.
The first four steps are based on the fact that a 32-bit number can be written as
(high 16 bits) * 65536 + (low 16 bits) =
(high 16 bits) * 65535 + (high 16 bits) + (low 16 bits) =
(high 16 bits) * 21845 * 3 + ((high 16 bits) + (low 16 bits))
So the whole thing is divisible by 3 if and only if the right parenthesis is divisible by 3. And so on, as this holds for 256 = 85 * 3 + 1, 16 = 5 * 3 + 1, and 4 = 3 + 1. (Of course, this is generally true for even powers of two; odd powers are one less than the nearest multiple of 3.)
The numbers that are input into the following steps will be larger than 16-bit, 8-bit, and 4-bit respectively in some cases, but that's not a problem, as we're not dropping any high-order bits when shifting right.

Restricting Binary Output to 8 bits or 4 bits

Here is my FIRST Question
Here is my code:
public class Bits{
public static void main(String args[]){
int i = 2 , j = 4;
int allOnes = ~0;
int left = allOnes << (j+1);
System.out.println("Binary Equivalent at this stage: " +Integer.toBinaryString(left));
}
}
The following is the output I'm getting:
Binary Equivalent at this stage: 11111111111111111111111111100000
How can I restrict it to only 8 bits from the right hand side. I mean 11100000 .
Please explain.
Here is my SECOND Question:
Also, I have one more Question which is totally different with the above one:
public static void main(String args[]){
int i = 2 , j = 4;
int allOnes = ~0; // will equal sequence of all 1s
int left = allOnes << (j+1);
System.out.println("Binary Equivalent at this stage: " +Integer.toBinaryString(left));
}
}
Since I didn't understand the following line:
int allOnes = ~0; // will equal sequence of all 1s
When I tried to output the value of "allOnes" then I got "-1" as my output.
I'm having hard time understanding the very next line which is as follows:
int left = allOnes << (j+1);
int allOnes = ~0;
Takes the integer 0 and applies the NOT operation bitwise so it will have all ones in its binary representation. Intagers use the two's complement format, meaning that a value of a word having all bits as one is value of -1.
If you only care about byte boundaries, then use a ByteBuffer
byte lastByte = ByteBuffer.allocate(4).putInt(i).array()[3];
To restrict this byte to the first four or last four bits, use lastByte & 0b11110000 or lastByte & 0b00001111
The integer representation of -1 is all 1's, i.e. 32 bits all set to 1. You can think of the first bit as -2^31 (note the negative sign), and of each subsequent bit as 2^30, 2^29, etc. Adding 2^0 + 2^1 + 2^2 ... + 2^30 - 2^31 = -1.
I suggest reading this tutorial on bitwise operations.
For #1 Integer.toBinaryString(left) is printing 32 bits (length of Integer), so if you just want the right 8 you can do the following:
Integer.toBinaryString(left).substring(24)
The ~ operator in Java inverts the the bit pattern. Thus 0 turns into ffff.
The << operator shifts the bits by x. You are shifting the bits to the left by 5 so you end up with 5 zeros on the right.
Here are all the bitwise operators for Java
First, a more general solution for the first question than what I've seen so far is
left &= (2 ^ n) - 1;
where n is the number of binary digits that you want to take from the right. This is based around the bitwise AND operator, &, which compares corresponding bits in two numbers and outputs a 1 if they are both 1s and 0 otherwise. For example:
10011001 & 11110000 == 10010000; // true
This is used to create what are known as bitmasks (http://en.wikipedia.org/wiki/Mask_(computing)). Notice how in this example how the left 4 bits of the first number are copied over to the result and how those same 4 bits are all ones in the second number? That's the idea in a bit mask.
So in your case, let's look at n = 8
left &= (2 ^ 8) - 1;
left &= 256 - 1;
left &= 255; // Note that &=, like += or *=, just means left = left & 255
// Also, 255 is 11111111 in binary so it can be used as the bitmask for
// the 8 rightmost bits.
Integer.toBinaryString(left) = "11100000";
Your second question is much more in depth, but you'd probably benefit most from reading the Wikipedia article (http://en.wikipedia.org/wiki/Two's_complement) instead of trying to understand a brief explanation here.
8 bits in decimal has a maximum value of 255. You can use the modulo (remainder) division operator to limit it to 8 bits at this point. For isntance:
int yournum = 35928304284 % 256;
will limit yournum to 8 bits of length. Additionally, as suggested in the comments, you can do this:
int yournum = 3598249230 & 255;
This works as well, and is actually preferred in this case, because it is much faster. The bitwise and function returns 1 if both associated bits are 1; since only the last 8 bits of 255 are one, the integer is implicitly limited to 255.
To answer your second question: A tilde is the bitwise inversion operator. Thus,
int allOnes = ~0;
creates an integer of all 1s. Because of the way twos complements works, that number actually represents -1.

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

What does <<= operator mean in Java?

Can you please explain this code snippet from HashMap constructor specifically the line
capacity <<= 1:
// Find a power of 2 >= initialCapacity
198 int capacity = 1;
199 while (capacity < initialCapacity)
200 capacity <<= 1;
It is equivalent to capacity = capacity << 1;.
That operation shifts capacity's bits one position to the left, which is equivalent to multiplying by 2.
The specific code you posted finds the smallest power of 2 which is larger than initialCapacity.
So if initialCapacity is 27, for example, capacity will be 32 (2^5) after the loop.
Just like var += 1 is about equivalent to var = var + 1, what you see here (var <<= 1) is about equivalent to var = var << 1, which is "set var to be the result of a 1-position binary left-shift of var."
In this very specific case, it's actually a slightly (runtime) faster way of expressing capacity *= 2 (because a bitwise left-shift of 1 position is equivalent to a multiplication by 2).
It is equivalent of
capacity = capacity << 1;
which shifts bits in capacity one position to the left (so i.e. 00011011 becomes 00110110).
every time this comes out of the loop the value of 'capacity' goes 2 raised by a power higher.
like initially it is 1 i.e.2^0; the operation(capacity <<= 1) for the first time makes it 2^1 and then 2^2 and so on.
May be you would like to see the more on it at http://www.tutorialspoint.com/java/java_basic_operators.htm

Categories

Resources