Bitwise AND with non-booleans - java

In the following Java program I cannot understand what this line does:
wert = (wert * mult + inkr) & 0x7FFFFFFFL;
I understand what the bitwise operators do in conditions, but there are principally two numbers (the hexadecimal is the maximum value of Integers in Java). I do not understand, why the & 0x7FFFFFFFL; has even some influence in this line. In my opinion, the variable wert should simply have the value of (wert * mult + inkr) because it's true.
Though I figured out that the & 0x7FFFFFFFL; obviously does have some influence only if (wert * mult + inkr) is negative. Why and what exactly happens in this line?
Annotation: This should be a program for simulating a lottery drawing. I am aware of the error in the program, right where the comment is. But this is not relevant for me right now.
Still it would be great if someone could me tell following not really Java-specific question: what sense got the variables mult and inkr?
public static void main(String args[]) {
int kugeln = 49;
int ziehen = 6;
int mult = 1103515245;
int inkr = 12345;
long wert = System.currentTimeMillis();
int zahlen[] = new int[kugeln];
for(int i = 0; i < kugeln; i++) {
zahlen[i] = i + 1;
wert = (wert * mult + inkr) & 0x7FFFFFFFL;
}
for(int i = 0; i < ziehen; i++) {
int index = (int)(wert / 10) % (49 - i);
int temp = zahlen[49 - i]; // Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 49
zahlen[49 - i] = zahlen[index];
zahlen[index] = temp;
wert = (wert * mult + inkr) & 0x7FFFFFFFL;
}
int superzahl = (int)(wert / 10) % 10;
for(int i = 0; i < ziehen; i++) {
System.out.println(zahlen[49 - i]);
}
System.out.println(superzahl);
}

Using bitwise AND with non-booleans will bitwise AND together all of the bits of the two numbers one by one.
In this case, the number 0x7FFFFFFFL is the hexadecimal representation of a number that is a 0 bit followed by 31 1 bits:
01111111111111111111111111111111
By ANDing this with an integer, you preserve the lower 31 bits (since 1 & x = x for any x) and clear the highest bit (since 0 & x = 0 for any x). Since Java uses a 32-bit signed two's-complement representation, this has the effect of clearing the sign bit, forcing the number to be positive.
My guess is that this program is using some sort of rolling hash function where the resulting number has to be positive. To do this, the code constantly updates the integer by combining it with more and more information, and at each step forces the number to be positive by clearing the sign bit.
Hope this helps!

Anding with 0x7FFFFFFFL results in only the 31 lowest bits getting included, the others get set to 0. The result is always positive because the sign bit is masked out.

int temp = zahlen[49 - i]; // Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 49
i is starting from 0 so zahlen[49 ] is called
int zahlen[] = new int[kugeln];
int kugeln = 49;
int a[] = new int [49];
a[49] will throw an exception always. Fom there is your exception.

Related

Rabin-Karp not working for large primes (gives wrong output)

So I was solving this problem (Rabin Karp's algorithm) and wrote this solution:
private static void searchPattern(String text, String pattern) {
int txt_len = text.length(), pat_len = pattern.length();
int hash_pat = 0, hash_txt = 0; // hash values for pattern and text's substrings
final int mod = 100005; // prime number to calculate modulo... larger modulo denominator reduces collisions in hash
final int d = 256; // to include all the ascii character codes
int coeff = 1; // stores the multiplier (or coeffecient) for the first index of the sliding window
/*
* HASHING PATTERN:
* say text = "abcd", then
* hashed text = 256^3 *'a' + 256^2 *'b' + 256^1 *'c' + 256^0 *'d'
*/
// The value of coeff would be "(d^(pat_len - 1)) % mod"
for (int i = 0; i < pat_len - 1; i++)
coeff = (coeff * d) % mod;
// calculate hash of the first window and the pattern itself
for (int i = 0; i < pat_len; i++) {
hash_pat = (d * hash_pat + pattern.charAt(i)) % mod;
hash_txt = (d * hash_txt + text.charAt(i)) % mod;
}
for (int i = 0; i < txt_len - pat_len; i++) {
if (hash_txt == hash_pat) {
// our chances of collisions are quite less (1/mod) so we dont need to recheck the substring
System.out.println("Pattern found at index " + i);
}
hash_txt = (d * (hash_txt - text.charAt(i) * coeff) + text.charAt(i + pat_len)) % mod; // calculating next window (i+1 th index)
// We might get negative value of t, converting it to positive
if (hash_txt < 0)
hash_txt = hash_txt + mod;
}
if (hash_txt == hash_pat) // checking for the last window
System.out.println("Pattern found at index " + (txt_len - pat_len));
}
Now this code is simply not working if the mod = 1000000007, whereas as soon as we take some other prime number (large enough, like 1e5+7), the code magically starts working !
The line at which the code's logic failed is:
hash_txt = (d * (hash_txt - text.charAt(i) * coeff) + text.charAt(i + pat_len)) % mod;
Can someone please tell me why is this happening ??? Maybe this is a stupid doubt but I just do not understand.
In Java, an int is a 32-bit integer. If a calculation with such number mathematically yields a result that needs more binary digits, the extra digits are silently discarded. This is called overflow.
To avoid this, the Rabin-Karp algorithm reduces results modulo some prime in each step, thereby keeping the number small enough that the next step will not overflow. For this to work, the prime chosen must be suitably small that
d * (hash + max(char) * coeff) + max(char)) < max(int)
Since
0 ≤ hash < p,
1 ≤ coeff < p,
max(char) = 216
max(int) = 231
any prime smaller than 27=128 will do. For larger primes, it depends on what their coeff ends up being, but even if we select one with the smallest possible coeff = 1, the prime must not exceed 223, which is much smaller than the prime you used.
In practice, one therefore uses Rabin-Karp with an integer datatype that is significantly bigger that the character type, such as a long (64 bits). Then, any prime < 239 will do.
Even then, if it worth noting that your reasoning
our chances of collisions are quite less (1/mod) so we dont need to recheck the substring
is flawed, because the probability is determined not by chance, but by the strings being checked. Unless you know the probability distribution of your inputs, you can't know what the probability of failure is. That's why Rabin-Karp rechecks the string to make sure.

Best way to convert parts of a string to int to convert from binary to float JAVA

I am writing a program where I have strings of 9 bits of "0" and "1" to convert to exponent (taking each index and doing 2 ^ n from right to left).
example: ["1","0","1"] = 2^2 + 0^1 + 2^0
I know this is wrong because of the errors I am getting but am confused what to do which will calculate it in an efficient manner.
expoBefore = (strNum.charAt(9)) * 1 + (strNum.charAt(8)) * 2 + (strNum.charAt(7)) * 4 + (strNum.charAt(6)) * 8 + (strNum.charAt(5)) * 16 + (strNum.charAt(4)) * 32 + (strNum.charAt(3)) * 64 + (strNum.charAt(8)) * 128;
for example for one of the strings I am passing through [11111111] I want it to add 1 * 2^0 + 1 * 2 ^1 + 1 * 2^2.....etc
Clarification edit:
What is a more efficient way of converting a string of 0's and 1's to an integer?
You're trying to multiply a character's ascii value with an integer.
You must take the integer value of this character and then multiply it with another integer. Hope this helps.
String str = "111";
int x = Character.getNumericValue(str.charAt(0));
int y = Character.getNumericValue(str.charAt(1));
int z = Character.getNumericValue(str.charAt(2));
System.out.println(x + y + z);
Output:
3
You need to use a loop.
Iterate over the binary string. For each character, add 2^x to an accumulator if the bit is set (where x is the position of the bit), otherwise, add 0.
String binary = "11111111";
int number = 0;
for(int i = binary.length() - 1; i >= 0; i--) {
char c = binary.charAt(i);
number += Integer.parseInt(c + "") * Math.pow(2, binary.length() - i - 1);
}
System.out.println(number); // prints 255
How to convert binary to decimal
Just use a for loop and increment down to miniplate each number
It is very inefficient to use Math.pow(2, i) in a loop.
Faster to keep the previous value and multiply by 2 each time through (code untested):
int ip = 1;
int sum = 0;
for ( int i = binary.length -1; i >= 0) {
if ( binary.charAt(i) == '1' ) {
sum += ip;
}
ip *= 2;
}
You may want to use long ints if the number gets large.
Also, be sure to check that binary contains only zeroes and ones.

Problems with Binary to Decimal conversion in java (arrays)

My assignment is to convert binary to decimal in a JLabel array without using pre-written methods (there's no user input). I have the right idea but for some reason the output is always a little bit off. I've gone through it countless times but I can't find anything wrong with my algorithm and I'm very confused as to why it doesn't produce the correct answer. I'd be very grateful if someone could help me out. Thanks!
Side note: I've read similar discussion threads regarding binary to decimal conversions but I don't understand how to do it with arrays.
Here is a snippet of my code:
private void convert()
{
int[] digit = new int[8]; //temporary storage array
int count = 0;
for(int x = 0; x < digit.length; x++)
{
digit[x] = Integer.parseInt(bits[x].getText()); //bits is the original array
count= count + digit[digit.length - 1 - x] * (int)(Math.pow(2, x));
}
label.setText("" + count);
}
You are following the binary number from left to right but are grabbing the wrong digit. You want the same digit but to multiply by the right power of two - first index being +n*128 and not +n*1
int count = 0;
for(int i = 0; i < bits.length; i++) {
count += Integer.parseInt(bits[i].getText()) * Math.pow(2, bits.length - i - 1);
}
Obviously there is a bug in your snippet.
You set the digit[x], but not set the digit[length - 1 - x].
for example, x = 0, you set the digit[0], but not set digit[7].
So there will be an error when you want use the digit[length - 1 -x] here :
count= count + digit[digit.length - 1 - x] * (int)(Math.pow(2, x));
This the correct code here:
private void convert()
{
int count = 0, length = 8;
for(int i = 0; i < length; count += Integer.parseInt(bits[i].getText()) * (1 << (length - 1 - i)), i++);
label.setText("" + count);
}
Have not test the code. But I think it will work.

How to sort digits of an integer using binary number technique?

Yesterday I went for an interview and they asked me to create a method which takes an integer value and displays the number with its digits in descending order. I used string manipulation and solved it but they asked me to do it using binary number technique. I still don't know how to approach this problem.
"Binary number technique"? It's a bullshit question, one where the correct answer is to walk out from the interview because it's a bullshit company.
Anyway, the best answer I can think of is
public static int solveBullshitTaskInASmartWay(int n) {
// get characters and sort them
char[] chars = Integer.toString(n).toCharArray();
Arrays.sort(chars);
// comparators don't work in Java for primitives,
// so you either have to flip the array yourself
// or make an array of Integer or Character
// so that Arrays.sort(T[] a, Comparator<? super T> c)
// can be applied
for (int i = 0, j = chars.length - 1; i < j; i++, j--) {
char t = chars[i]; chars[i] = chars[j]; chars[j] = t;
}
// reconstruct the number
return Integer.parseInt(new String(chars));
}
There is no numeric way to sort a number's digits, if you're expecting a nifty mathematical answer you will be waiting for a while.
EDIT: I need to add this - "digit" is solely a property of display of numbers. It is not a property of a number. Mathematically, the number 0b1000 is the same as 0x8 or 0o10, or 008.00000, or 8e0 (or even trinary 22, if anyone used trinary; alas, no conventional notation for that in programming). It is only the string representations of numbers that have digits. Solving this problem without use of characters or strings is not only pretty hard, it is stupid.
EDIT2: It is probably obvious, but I should make it clear that I have no beef with the OP, it is the interviewer I that I am entirely laying the blame on.
The is a simple (but not efficient) way of doing it without conversion to string. You can perform insertion sort on digits by extracting them from number using modulo and division, comparing them, and swapping if needed. There will be at most 9*8 comparsions need.
Here is code in C++
int sortDigits(int number)
{
for(int j = 0; j < 9; ++j) //because number can have 9+1 digits (we don't need 10 because digits are sorted in pairs)
{
int mul = 1;
for(int i = 0; i < 8; ++i) //because with i == 7 mul * 10 is biggest number fitting in int (will extract last digit)
{
if (mul * 10 > number) break; //by doing that we ensure there will be no zeroes added to number
int digitRight = number / mul % 10;
int digitLeft = number / (mul * 10) % 10;
if(digitRight > digitLeft) //swapping digits
{
/*
number -= digitLeft * mul * 10;
number += digitLeft * mul;
number -= digitRight * mul;
number += digitRight * mul * 10;
*/
number -= digitLeft * mul * 9;
number += digitRight * mul * 9;
}
mul *= 10;
}
}
return number;
}

Java results differ for (int)Math.pow(2,x) and 1<<x

Why do the following two operations yield different results in Java for x = 31 or 32 but the same results for x=3?
int x=3;
int b = (int) Math.pow(2,x);
int c = 1<<x;
Results:
x=32: b=2147483647; c=1;
x=31: b=2147483647; c=-2147483648;
x=3: b=8 ; c=8
There are multiple issues at play:
An int can only store values between -2147483648 and 2147483647.
1 << x only uses the lowest five bits of x. Thus, 1 << 32 is by definition the same as 1 << 0.
Shift operations are performed on the two's-complement integer representation of the value of the left operand; this explains why 1 << 31 is negative.
Math.pow(2, 32) returns a double.
(int)(d), where d is a double greater than 2147483647 returns 2147483647 ("the largest representable value of type int").
What this interview question does is show that (int)Math.pow(2, x) and 1 << x are not equivalent for values of x outside the 0...30 range.
P.S. It is perhaps interesting to note that using long in place of int (and 1L in place of 1) would give yet another set of results different from the other two. This holds even if the final results are converted to int.
According to the documentation Math.pow will promote both of its arguments to double and return double. Obviously when the returned result is double and you cast it to int you'll get only the highest 32 bits and the rest will be truncated - hence you always get the (int) Math.pow(2,x); value. When you do bitshift you always work with ints and hence an overflow occurs.
Consider the limits of the type int. How large a number can it hold?
Here's a micro-benchmark for the case of a long. On my laptop (2.8GHz), using shift instead of Math.pow is over 7x faster.
int limit = 50_000_000;
#Test
public void testPower() {
Random r = new Random(7);
long t = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int p = r.nextInt(63);
long l = (long)Math.pow(2,p);
}
long t1 = System.currentTimeMillis();
System.out.println((t1-t)/1000.0); // 3.758 s
}
#Test
public void testShift() {
Random r = new Random(7);
long t = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int p = r.nextInt(63);
long l = 1L << p;
}
long t1 = System.currentTimeMillis();
System.out.println((t1-t)/1000.0); // 0.523 s
}
int is 32 bits in size and since it is signed (by default), the first bit is used for the sign. When you shift left 31 bits, you get the Two's Compliment, which is -(2^32). When you shift left 32 bits, it just loops all the way back around to 1. If you were to do this shifting with longs instead of ints, you would get the answers you expect (that is until you shift 63+ bits).

Categories