Porting '&' operator from Java to Javascript: Overflow issues - java

Consider the following JAVA statement:
System.out.println(3232235776l & 0xFFFFFFFE);
The output is: 3232235776
When I re-write the statement in JavaScript:
console.log(3232235776 & 0xFFFFFFFE);
The output is: -1062731520
Q. Is there a way to work around this overflow in JavaScript and get the right output?
For the sake of simplicity, I did not post the function I was converting from Java. Here it is. Please assume ipToLong and longToIp as working blackboxes in both Java and JavaScript (i.e. they do the right ip to long int conversion and vice-versa correctly, in both Java and JS, linted and unit tested).
Taken from here: https://stackoverflow.com/a/5032908/504674
Now, can someone help me convert the below Java line to JavaScript correctly?
Specifically: long maskedBase = start & mask;.
Full function to be converted:
public static List<String> range2cidrlist( String startIp, String endIp ) {
int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000,
0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,
0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,
0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
0xFFFFFFFF
};
long start = ipToLong(startIp);
long end = ipToLong(endIp);
ArrayList<String> pairs = new ArrayList<String>();
while ( end >= start ) {
byte maxsize = 32;
while ( maxsize > 0) {
long mask = CIDR2MASK[maxsize -1];
long maskedBase = start & mask;
if ( maskedBase != start ) {
break;
}
maxsize--;
}
double x = Math.log( end - start + 1) / Math.log( 2 );
byte maxdiff = (byte)( 32 - Math.floor( x ) );
if ( maxsize < maxdiff) {
maxsize = maxdiff;
}
String ip = longToIp(start);
pairs.add( ip + "/" + maxsize);
start += Math.pow( 2, (32 - maxsize) );
}
return pairs;
}

Instead of using & to remove the bit you want, you could subtract it.
long n = 3232235776L;
System.out.println(n - (n & 1)); // instead of 1 you can use ~0xFFFFFFFE
This shouldn't suffer from an overflow in your case.

Bitwise operators treat their operands as a sequence of 32 bits (zeros and ones)
says the Mozilla documentation.
You start out with a floating point value, it is converted to a 32 bit value. But because it's too big, it will overflow.
I suggest you try the following instead:
var number = 3232235776;
if (number % 2 == 1) {
number = number - 1;
}
Of course, you could write this more succinctly, but also more cryptic:
var number = 3232235776;
number = number - (number % 2);
That should be semantically equivalent for both positive and negative numbers.
Sign extension
In Java, 0xFFFFFFFE is a 32bit integer representing -2 when ANDing this with a long, it gets converted to a 64bit integer: 0xFFFF_FFFF_FFFF_FFFE, so all this effectively does is clear the last bit, i.e. round down (down, not towards zero).
I'm not sure if that's what you wanted. If it is intended, it's probably not something I would like in my codebase.
No sign extension
Here is the equivalent JavaScript code, if you intended this to happen without sign extension:
var number = 3232235776;
if (number % 2 == 1) {
number = number - 1;
}
number = number % 0x100000000; // That's 8 zeroes, i.e. keep the last 4 bytes

Related

Reverse Engineering - What's Kind of Algorithm In This Code?

Someone can help me to discover what type of algorithm is this?
public class hf1 {
public static final String[] f3650a = {"0sFU#W>Ao*BT64?[L5aONSK.'"...};
public static final String[] f3651b = {" \bB\u0017\u001e)YBN\u001eT/\u001e4V\u0001ZT/6VV"...};
public static final String[] f3652c = {"\u0000\u0000\u0013\u00006\u0000\\\u0000\u0000¢\u0000¹\u0000¿\u0000"...};
public static String m5192a(int i) {
int i2 = i / 4096;
int i3 = i % 4096;
int i4 = i + 1;
int i5 = i4 / 4096;
int i6 = i4 % 4096;
String[] strArr = f3652c;
String str = strArr[i2];
String str2 = strArr[i5];
int i7 = i3 * 2;
int charAt = ((str.charAt(i7 + 1) & 65535) << 16) | (str.charAt(i7) & 65535);
int i8 = i6 * 2;
int charAt2 = ((str2.charAt(i8 + 1) << 16) | str2.charAt(i8)) - charAt;
char[] cArr = new char[charAt2];
for (int i9 = 0; i9 < charAt2; i9++) {
int i10 = charAt + i9;
int charAt3 = f3651b[i10 / 8192].charAt(i10 % 8192) & 65535;
cArr[i9] = f3650a[charAt3 / 8192].charAt(charAt3 % 8192);
}
return new String(cArr);
}
}
If i call m5192a(1) passing any int index as parameter, the code returns a String. It's like some kind of hiding plain strings on the source code.
Someone have any idea of a possible reverse code? To transform plain string in to this? Is this a known technique with a name?
I'm not sure about a "known technique with a name" - perhaps keywords like "inverse function" or "bidirectionalization" might help, e.g. In pure functional languages, is there an algorithm to get the inverse function?
For this particular function, luckily it seems pretty straightforward to invert as long as the f365xx string constants abide by some certain properties. Notice that cArr is filled one-by-one and each character is independent of each other. We can try to use both the characters and the length of the string to try to decode the input i. Specifically,
A single character will give us candidates for i10, which will give us candidates for charAt. Repeating over all the characters, hopefully only one candidate will work for every character, and that candidate will give us i7/i2
-> i2/i3 -> i if the strings are "benevolent".
If the strings are not benevolent, then the length of the string will give us candidates for charAt2 which, together with the candidates for charAt, will give us candidates for i8/i6. Hopefully there is only one candidate pair i6/i8 -> i5/i6 -> -> i4 -> i if the string constants are benevolent.
If the strings are still not benevolent, then it is unsolvable since the function is not one-to-one.
I'll outline the algorithm for the 2 bullet points now, but as a disclaimer, I haven't tested this and it's just pseudocode.
From a character
Let's say you start with the first character, cArr[0]. If we focus on the 3 lines inside the for loop,
int i10 = charAt + i9;
int charAt3 = f3651b[i10 / 8192].charAt(i10 % 8192) & 65535;
cArr[i9] = f3650a[charAt3 / 8192].charAt(charAt3 % 8192);
Then we can get charAt3 by finding where cArr[0] appears in f3650a. For example,
charAt3candidates = []
for i = 0 to length(f3650a)-1:
indexCandidates = f3650[i].indexOf(cArr[0])
for indexCandidate in indexCandidates:
charAt3candidate = i * 8192 + indexCandidate
if indexCandidate >= 8192 or charAt3candidate >= 65536:
continue
charAt3candidates.append(charAt3candidate)
Note that we filter out indexCandidate >= 8192 and charAt3candidate >= 65536 due to modulo's and bitwise and's that make greater values impossible (x & 65535 == x % 65536 since 65536 = 2^16).
Do a similar process to find the candidates for i10 and subtract i9 to get candidates for charAt. If you have more than one candidate, repeat this process for every character in cArr and keep only the candidates of charAt which are valid for every character in cArr. Even after repeating for every character in cArr, you may still have many candidates.
For each candidate of charAt, use the right-half of the expression for charAt:
charAt % 65536 = (str.charAt(i7) & 65535)
combined with str = f3652c[i2] to try to find i2/i7 the same way we tried to find charAt3 and i10. Note that the left half of the expression, ((str.charAt(i7 + 1) & 65535) << 16), doesn't matter (for now). Hope and pray that this only gives you one possible choice of i2/i7. If so, use it to find i2/i3 -> i. If there's more than one option, then we have to try using the length of the string.
From the length of the string
The length of the string gives us charAt2, and we can use a similar process as before to find all the candidates for i8 and str2 (i5). Note in this process we have to try with every possible candidate for charAt. Hopefully there is only one candidate pair for i8/i5 remaining. If so, use it to find i5/i6 -> i4 -> i. If there are more than 1 candidate, then the function is not one-to-one and it's impossible to invert.
Good luck!

Karatsuba algorithm implementation: works for small ns, breaks for bigger ns

I'm working on an implementation of the Karatsuba algorithm of multiplying numbers, but unlike most implementations using Strings as the primary data structure instead of BigNumbers or longs. I've written a recursive solution to the problem that appears to work for all n < 6, but for some reason it fails to work for odd ns greater than 6, despite all of the base cases working. Here's the karatsuba part of the program, with a few prints left behind from debugging. All of the methods used in this should work as intended, I tested them thoroughly. For a value factor1 = "180" and factor2 = "109", the correct result is outputted. For a value factor1 = "1111" and factor2 = "1111" the correct result is outputted. For a factor1 = "2348711" and factor2 = "8579294" the program outputs "20358060808034" when it should output "20150282190034". I've tried backtracing the logic, and I can't find where exactly it goes wrong. If anyone has any insight as to where something may not work, any help is appreciated.
public static String multiply(String factor1, String factor2) {
// base case of length = 1
System.out.println("Factor1 " + factor1 + " factor2 " + factor2);
if (factor1.length() == 1 && factor2.length() == 1) {
return smallNumberMultiplication(factor1, factor2);
} else if (factor1.length() == 1 && factor2.length() == 2) { //these conditions needed for odd-size #s
return smallNumberMultiplication(factor1, factor2); // max iteration = 10
} else if (factor1.length() == 2 && factor2.length() == 1) {
return smallNumberMultiplication(factor2, factor1); // max iteration = 10
}
// check which factor is smaller, find the index at which the value is split
int numberLength = factor1.length();
int middleIndex = numberLength / 2;
// Find the power to which 10 is raised such that it follows Karatsuba's algorithm for ac
int powerValue = numberLength + numberLength % 2;
// divide both numbers into two parts bounded by middleIndex place
String[] tempSplitString = splitString(factor1, middleIndex);
String f1Large = tempSplitString[0], f1Small = tempSplitString[1];
tempSplitString = splitString(factor2, middleIndex);
String f2Large = tempSplitString[0], f2Small = tempSplitString[1];
String multiplyHighestNumbers, multiplySmallestNumbers, multiplyMiddleNumbers;
// large factor1 * large factor2
multiplyHighestNumbers = multiply(f1Large, f2Large);
// Multiply (f1Large + f1Small)*(f2Large + f2Small)
multiplyMiddleNumbers = multiply(addTwoValues(f1Large, f1Small), addTwoValues(f2Large, f2Small));
// small factor1 * small factor2
multiplySmallestNumbers = multiply(f1Small, f2Small);
// add trailing zeros to values (multiply by 10^powerValue)
String finalHighestNumber = addTrailingZeros(multiplyHighestNumbers, powerValue);
String finalMiddleNumber = addTrailingZeros(
subtractTwoValues(subtractTwoValues(multiplyMiddleNumbers, multiplyHighestNumbers),
multiplySmallestNumbers),
powerValue / 2);
String finalSmallestNumber = multiplySmallestNumbers;
// add each part together
return removeLeadingZeros(addTwoValues(addTwoValues(finalHighestNumber, finalMiddleNumber), finalSmallestNumber));
}
I noticed two problems:
using different values for splitting (middleIndex) and shifting (powerValue) (needlessly implemented by tacking on zeroes).
For productHighParts("multiplyHighestNumbers") to be closer in length to the other products, use (factor1.length() + factor2.length()) / 4 (half the average length of both factors).
this length has to be the length of the less significant part in splitString(), not the leading part.
(Note that the first two controlled statements can be combined:
if (factor1.length() <= 1 && factor2.length() <= 2).)

How to properly handle max/min int value edge case-Java

I am working on a problem from LeetCode (not an interview question just practicing) that asks the following:
Given a sorted integer array nums, where the range of elements are in the inclusive range [lower, upper], return its missing ranges.
The code that I came up with fails for inputs where the nums array is [-2147483648,2147483647] and lower/upper are -2147483648/2147483647 respectively. The part of my code that actually answers the question is:
if (nums[0]-lower > 1) {
String range = lower + "->" + (nums[0]-1);
ans.add(range);
}
else if (nums[0]-lower == 1) {
String range = new Integer(lower).toString();
ans.add(range);
}
for (int i = 1; i < nums.length; i++) {
if (nums[i] - nums[i-1] > 2) {
String range = nums[i-1]+1 + "->" + (nums[i]-1);
ans.add(range);
}
else if (nums[i] - nums[i-1] == 2) {
String range = new Integer(nums[i]-1).toString();
ans.add(range);
}
}
I was wondering how best to handle this edge case, not just for this question but generally. Do I just add extra if-statements to my code to specifically handle these two numbers (or if addition/subtraction of numbers causes the int value to overflow) or is there a more elegant way to handle this?
The maximum value of an int is 231-1 which is 2147483647, but the difference between that number and any negative number is larger than that number itself.
So all your subtraction expressions like nums[0]-lower overflow with [-2147483648,2147483647] (or [-1,2147483647]).
You can check it with this:
System.out.println(2147483647 - -1);
This prints out -2147483648 even though you would expect it to be 2147483648.
One easy fix is to do the calculations as a 64-bit long. Change all your subtractions like below to cast the expression to long.
if (nums[0] - (long)lower > 1) {
Take the above example and change it to:
System.out.println(2147483647 - (long) -1);
This will correctly print 2147483648.

Bit circular shift just shows a bunch of zeros

I wanted to play around with bitwise operators and specifically wanted to make a circular bitwise shift. So say that I have the number 101. Shifting it left 1 step should result in 011. Now when I try this example in Java, it just shows a bunch of zeros, like this:
//Circular right shift
private static void testCircular() {
int x = 37;
System.out.println(x + " Is " + Integer.toBinaryString(x));
x = (x >>> 8) | (x << (Integer.SIZE - 8));
System.out.println(x + " Is " + Integer.toBinaryString(x));
}
This gives me the following result:
37 Is 100101
620756992 Is 100101000000000000000000000000
As you can see, it merly added trailing zeroes, not shifting anything. I also tried the state = Integer.rotateRight(state,8); method, it does the same thing. What am I missing here?
I think it works as expected, what You are missing is full representation of number in bits - when You print it's skipping zeros at the beginning. Integer is stored in 32 bits, so full representation looks like this:
int x = 37;
00000000000000000000000000100101
x = (x >>> 8) | (x << (Integer.SIZE - 8));
00100101000000000000000000000000
EDIT
Here is a method to get a full string representation of an Integer:
public static String toBinaryStringWithLeadingZeros(int x) {
StringBuffer buf = new StringBuffer(32);
char[] arr = new char[Integer.numberOfLeadingZeros(x)];
Arrays.fill(arr, '0');
buf.append(arr);
buf.append(Integer.toBinaryString(x));
return buf.toString();
}
Your code and Integer.rotateRight(state,8); give the same result and work as expected. intin java is 4 bytes so 100101 is actually:
00000000000000000000000000100101
When you shift rotate it right 8 times you get:
00100101000000000000000000000000
Integer.toBinaryString(x)) discards leading zeros so what you see is 100101 in the first case and 100101000000000000000000000000in the second (first two zeros are discarded).

How to find the closest value of 2^N to a given input?

I somehow have to keep my program running until the output of the exponent function exceeds the input value, and then compare that to the previous output of the exponent function. How would I do something like that, even if in just pseudocode?
Find logarithm to base 2 from given number => x := log (2, input)
Round the value acquired in step 1 both up and down => y := round(x), z := round(x) + 1
Find 2^y, 2^z, compare them both with input and choose the one that suits better
Depending on which language you're using, you can do this easily using bitwise operations. You want either the value with a single 1 bit set greater than the highest one bit set in the input value, or the value with the highest one bit set in the input value.
If you do set all of the bits below the highest set bit to 1, then add one you end up with the next greater power of two. You can right shift this to get the next lower power of two and choose the closer of the two.
unsigned closest_power_of_two(unsigned value)
{
unsigned above = (value - 1); // handle case where input is a power of two
above |= above >> 1; // set all of the bits below the highest bit
above |= above >> 2;
above |= above >> 4;
above |= above >> 8;
above |= above >> 16;
++above; // add one, carrying all the way through
// leaving only one bit set.
unsigned below = above >> 1; // find the next lower power of two.
return (above - value) < (value - below) ? above : below;
}
See Bit Twiddling Hacks for other similar tricks.
Apart from the looping there's also one solution that may be faster depending on how the compiler maps the nlz instruction:
public int nextPowerOfTwo(int val) {
return 1 << (32 - Integer.numberOfLeadingZeros(val - 1));
}
No explicit looping and certainly more efficient than the solutions using Math.pow. Hard to say more without looking what code the compiler generates for numberOfLeadingZeros.
With that we can then easily get the lower power of 2 and then compare which one is nearer - the last part has to be done for each solution it seems to me.
set x to 1.
while x < target, set x = 2 * x
then just return x or x / 2, whichever is closer to the target.
public static int neareastPower2(int in) {
if (in <= 1) {
return 1;
}
int result = 2;
while (in > 3) {
in = in >> 1;
result = result << 1;
}
if (in == 3) {
return result << 1;
} else {
return result;
}
}
I will use 5 as input for an easy example instead of 50.
Convert the input to bits/bytes, in this case 101
Since you are looking for powers of two, your answer will all be of the form 10000...00 (a one with a certain amount of zeros). You take the input value (3 bits) and calculate the integer value of 100 (3 bits) and 1000 (4 bits). The integer 100 will be smaller then the input, the integer 1000 will be larger.
You calculate the difference between the input and the two possible values and use the smallest one. In this case 100 = 4 (difference of 1) while 1000 = 8 (difference of 3), so the searched answer is 4
public static int neareastPower2(int in) {
return (int) Math.pow(2, Math.round(Math.log(in) / Math.log(2)));
}
Here's the pseudo code for a function that takes the input number and returns your answer.
int findit( int x) {
int a = int(log(x)/log(2));
if(x >= 2^a + 2^(a-1))
return 2^(a+1)
else
return 2^a
}
Here's a bitwise solution--it will return the lessor of 2^N and 2^(N+1) in case of a tie. This should be very fast compare to invoking the log() function
let mask = (~0 >> 1) + 1
while ( mask > value )
mask >> 1
return ( mask & value == 0 ) ? mask : mask << 1

Categories