Different implementations of compare method for Long, Integer and Short? - java

Why are the implementations of the static method compare for Long, Integer and Short in Java's library different?
For Long:
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
For Integer:
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
For Short:
public static int compare(short x, short y) {
return x - y;
}

If you try:
System.out.println(Long.MIN_VALUE - Long.MAX_VALUE);
or
System.out.println(Integer.MIN_VALUE - Integer.MAX_VALUE);
You will get 1 because of overflow(update: should be underflow here, as mentioned in another answer), which is incorrect.
However, with
System.out.println(Short.MIN_VALUE - Short.MAX_VALUE);
you will get correct value -65535, because short will be converted to int before - operation, which prevents the overflow.

x - y is presumably the most efficient (since the alternative involves branching twice), so that's used for short.
But x - y can't be used for int or long, because this will overflow when the resulting value doesn't fit in an int, which can give a positive value when the result should be negative, or a negative value when the result should be positive (or zero in either case).
Note: when subtracting two shorts, the resulting value is of type int, so that can never overflow.
// long - long
System.out.println((int)(2147483649l - 1l)); // -2147483648, not 2147483648
// int - int
System.out.println(-2147483648 - 1); // 2147483647, not -2147483649
// int - int
System.out.println(1 - -2147483648); // -2147483647, not 2147483649
// short - short
short s1 = -32768, s2 = 1;
System.out.println(s1 - s2); // -32769, as desired
For what it's worth: the values above were chosen since they're roughly around the minimum and maximum values for int (and short), to demonstrate at which point it overflows.

int can have values between [-2147483648, +2147483647]. If you subtract -2147483648 from +2147483647, you will get 4294967295. This can't be stored in an int, therefore we use this for comparing 2 ints
return (x < y) ? -1 : ((x == y) ? 0 : 1);
The same is the case with long.

Related

Unsigned modulo in Java

I'm porting some c code which is doing a modulo on an uint32_t. An uint32_t fits in a Java int bit-wise, but I cannot figure out how to perform a modulo operation on it without converting to a long. This is the code I have right now:
int i = 0xffffffff;
long asUnsigned = Integer.toUnsignedLong(i);
int mod = (int) (asUnsigned % 42L);
Can I perform this modulo calculation without converting to long?
Use Integer.remainderUnsigned(int dividend, int divisor) (javadoc):
Returns the unsigned remainder from dividing the first argument by the second where each argument and the result is interpreted as an unsigned value.
#that other guy's answer is preferred for Java 8+. I'll leave this here in case it's useful for anyone using older versions of Java.
Converting to a long is almost certainly the best way to do this.
Otherwise, you will need to branch; to get the correct result for a negative int value, you will need to adjust for the fact that the unsigned number that the int represents is offset by 232, and this offset generally won't have a remainder of 0 when you divide by the modulus. If the modulus is a constant (42 in your example) then you can hardcode the offset:
static int unsignedMod42(int x) {
if(x >= 0) {
return x % 42;
} else {
// 2**32 = 4 (mod 42)
return ((x % 42) + 42 + 4) % 42;
}
}
If the modulus is a variable then you have to compute the correct offset at runtime:
static int unsignedMod(int x, int y) {
if(y <= 0 || y * y <= 0) {
throw new IllegalArgumentException("y = " + y);
} else if(x >= 0) {
return x % y;
} else {
// compute 2**32 mod y, by repeated squaring
int offset = 2;
for(int i = 0; i < 5; ++i) { offset = (offset * offset) % y; }
return ((x % y) + y + offset) % y;
}
}
Note that because the offset here is being computed by repeated squaring, we can't allow a modulus for which the multiplication might overflow. There is presumably a better way to compute the correct offset - by repeated multiplication would allow a modulus up to Integer.MAX_VALUE / 2, for example.

How to write a LessThan method without using the operator

How would you recursively write a method that checks if a number is less than the other without using the '<' operator?
You can only use the plus, minus, times, and equals operators.
It must be recursive
x and y will always be 0 or greater
Should return boolean
If needed, you can make other methods but they must follow rules above.
Cove I've got so far:
public static boolean isLessThan(int x, int y) {
if(x == y - 1) return true;
if(x == y + 1) return false;
if(x == y) return false;
return isLessThan((x), (y-1)) || isLessThan((x-1), y);
}
Because you have made a good-faith attempt by writing your own code, and because I see this is a kind of puzzle, I'm offering you below code which has only a single recursive call rather than having two recursive calls like in your code.
I think this is as simple as it gets while satisfying the constraints.
What it does: it counts down both numbers to zero, and checks which one reaches zero first. If both reach zero at the same time, the result should be false, but simply checking whether y is zero already includes that check.
public static boolean isLessThan(int x, int y) {
if (y == 0) {
return false;
}
if (x == 0) {
return true;
}
return isLessThan(x - 1, y - 1);
}
#Andreas' answer is more efficient than the above. My aim initially was for a short, clean answer.
I've tried to create a shorter bitshift approach.
Although harder to grasp than the counting example, it has a better complexity and it has an equal amount of lines as the above code (I'm not counting that constant as I could include it inside the code at the expense of readability).
Note that this code shifts left rather than right and - it checks the most significant bit first.
public static final int HIGH_BIT = 1 << 31;
public static boolean isLessThan(int x, int y) {
if (x == y) {
return false;
}
if ((x & HIGH_BIT) != (y & HIGH_BIT)) {
return (y & HIGH_BIT) == HIGH_BIT;
}
return isLessThan(x << 1, y << 1);
}
Note: if != is disallowed, you can change the second if statement to:
if (((x ^ y) & HIGH_BIT) == HIGH_BIT)
Also note that the complexity is really O(1) as, although the algorithm is theoretically O(log n), Java ints are 32 bits so the upper bounds is O(32) which is the same as O(1).
You could do it like the answer to this question:
Bitwise operations equivalent of greater than operator
However that doesn't honor rule 2: It must be recursive.
According to comment, rule 1 should be:
You can only use plus, minus, multiply, equals, and bitwise operators.
With the use of the right-shift operator, we can get a solution in O(log n) time, unlike answer by Erwin Bolwidt, which is O(n) time, and likely to cause StackOverflowError.
public static boolean isLessThan(int x, int y) {
return compare(x, y) == -1;
}
private static int compare(int x, int y) {
if (x == y)
return 0; // x == y
if (x == 0)
return -1; // x < y
if (y == 0)
return 1; // x > y
// Compare higher bits. If different, then that is result
int cmp = compare(x >> 1, y >> 1);
if (cmp != 0)
return cmp;
// Only bit 0 differs, so two choices:
// x0 == 1 && y0 == 0 -> return 1
// x0 == 0 && y0 == 1 -> return -1
return (x & 1) - (y & 1);
}
If != is not allowed, code can be changed to:
// same code up to and including recursive call
if (cmp == 0)
return (x & 1) - (y & 1);
return cmp;

Compare two integers using bit operator

I need to compare two integer using Bit operator.
I faced a problem where I have to compare two integers without using comparison operator.Using bit operator would help.But how?
Lets say
a = 4;
b = 5;
We have to show a is not equal to b.
But,I would like to extend it further ,say,we will show which is greater.Here b is greater..
You need at least comparison to 0 and notionally this is what the CPU does for a comparison. e.g.
Equals can be modelled as ^ as the bits have to be the same to return 0
(a ^ b) == 0
if this was C you could drop the == 0 as this can be implied with
!(a ^ b)
but in Java you can't convert an int to a boolean without at least some comparison.
For comparison you usually do a subtraction, though one which handles overflows.
(long) a - b > 0 // same as a > b
subtraction is the same as adding a negative and negative is the same as ~x+1 so you can do
(long) a + ~ (long) b + 1 > 0
to drop the +1 you can change this to
(long) a + ~ (long) b >= 0 // same as a > b
You could implement + as a series of bit by bit operations with >> << & | and ^ but I wouldn't inflict that on you.
You cannot convert 1 or 0 to bool without a comparison operator like Peter mentioned. It is still possible to get max without a comparison operator.
I'm using bit (1 or 0) instead of int to avoid confusion.
bit msb(x):
return lsb(x >> 31)
bit lsb(x):
return x &1
// returns 1 if x < 0, 0 if x >= 0
bit isNegative(x):
return msb(x)
With these helpers isGreater(a, b) looks like,
// BUG: bug due to overflow when a is -ve and b is +ve
// returns 1 if a > b, 0 if a <= b
bit isGreater_BUG(a, b):
return isNegative(b - a) // possible overflow
We need two helpers functions to detect same and different signs,
// toggles lsb only
bit toggle(x):
return lsb(~x)
// returns 1 if a, b have same signs (0 is considered +ve).
bit isSameSigns(a, b):
return toggle(isDiffSigns(a, b))
// returns 1 if a, b have different signs (0 is considered +ve).
bit isDiffSigns(a, b):
return msb(a ^ b)
So with the overflow issue fix,
// returns 1 if a > b, 0 if a <= b
bit isGreater(a, b):
return
(isSameSigns(a, b) & isNegative(b - a)) |
(isDiffSigns(a, b) & isNegative(b))
Note that isGreater works correctly for inputs 5, 0 and 0, -5 also.
It's trickier to implement isPositive(x) properly as 0 will also be considered positive. So instead of using isPositive(a - b) above, isNegative(b - a) is used as isNegative(x) works correctly for 0.
Now max can be implemented as,
// BUG: returns 0 when a == b instead of a (or b)
// returns a if a > b, b if b > a
int max_BUG(a, b):
return
isGreater(a, b) * a + // returns 0 when a = b
isGreater(b, a) * b //
To fix that, helper isZero(x) is used,
// returns 1 if x is 0, else 0
bit isZero(x):
// x | -x will have msb 1 for a non-zero integer
// and 0 for 0
return toggle(msb(x | -x))
So with the fix when a = b,
// returns 1 if a == b else 0
bit isEqual(a, b):
return isZero(a - b) // or isZero(a ^ b)
int max(a, b):
return
isGreater(a, b) * a + // a > b, so a
isGreater(b, a) * b + // b > a, so b
isEqual(a, b) * a // a = b, so a (or b)
That said, if isPositive(0) returns 1 then max(5, 5) will return 10 instead of 5. So a correct isPositive(x) implementation will be,
// returns 1 if x > 0, 0 if x <= 0
bit isPositive(x):
return isNotZero(x) & toggle(isNegative(x))
// returns 1 if x != 0, else 0
bit isNotZero(x):
return msb(x | -x)
Using binary two’s complement notation
int findMax( int x, int y)
{
int z = x - y;
int i = (z >> 31) & 0x1;
int max = x - i * z;
return max;
}
Reference: Here
a ^ b = c // XOR the inputs
// If a equals b, c is zero. Else c is some other value
c[0] | c[1] ... | c[n] = d // OR the bits
// If c equals zero, d equals zero. Else d equals 1
Note: a,b,c are n-bit integers and d is a bit
The solution in java without using a comparator operator:
int a = 10;
int b = 12;
boolean[] bol = new boolean[] {true};
try {
boolean c = bol[a ^ b];
System.out.println("The two integers are equal!");
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
System.out.println("The two integers are not equal!");
int z = a - b;
int i = (z >> 31) & 0x1;
System.out.println("The bigger integer is " + (a - i * z));
}
I am going to assume you need an integer (0 or 1) because you will need a comparison to get a boolean from integer in java.
Here, is a simple solution that doesn't use comparison but uses subtraction which can actually be done using bitwise operations (but not recommended because it takes a lot of cycles in software).
// For equality,
// 1. Perform r=a^b.
// If they are equal you get all bits 0. Otherwise some bits are 1.
// 2. Cast it to a larger datatype 0 to have an extra bit for sign.
// You will need to clear the high bits because of signed casting.
// You can split it into two parts if you can't cast.
// 3. Perform -r.
// If all bits are 0, you will get 0.
// If some bits are not 0, then you get a negative number.
// 4. Shift right to extract MSB.
// This will give -1 (because of sign extension) for not equal and 0 for equal.
// You can easily convert it to 0 and 1 by adding 1 (I didn't include it in below function).
int equality(int a, int b) {
long r = ((long)(a^b)) ^0xffffffffl;
return (int)(((long)-r) >> 63);
}
// For greater_than,
// 1. Cast a and b to larger datatype to get more bits.
// You can split it into two parts if you can't cast.
// 2. Perform b-a.
// If a>b, then negative number (MSB is 1)
// If a<=b, then positive number or zero (MSB is 0)
// 3. Shift right to extract MSB.
// This will give -1 (because of sign extension) for greater than and 0 for not.
// You can easily convert it to 0 and 1 by negating it (I didn't include it in below function).
int greater_than(int a, int b) {
long r = (long)b-(long)a;
return (int)(r >> 63);
}
Less than is similar to greater but you swap a and b.
Trivia: These comparison functions are actually used in security (Cryptography) because the CPU comparison is not constant-time; aka not secure against timing attacks.

ceil conterpart for Math.floorDiv in Java?

Is there any ceil counterpart for Math.floorDiv()
How to calculate it fastest way with what we have?
UPDATE
The code for floorDiv() is follows:
public static long floorDiv(long x, long y) {
long r = x / y;
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
Can we code ceil the similar way?
UPDATE 2
I saw this answer https://stackoverflow.com/a/7446742/258483 but it seems to have too many unnecessary operations.
There is none in the Math class, but you can easily calculate it
long ceilDiv(long x, long y){
return -Math.floorDiv(-x,y);
}
For example, ceilDiv(1,2) = -floorDiv(-1,2) =-(-1)= 1 (correct answer).
I'd also just use the negation of floorMod, but if you are going to define your own function, you could simply adapt the above code:
public static int ceilDiv(int x, int y) {
int r = x / y;
// if the signs are the same and modulo not zero, round up
if ((x ^ y) >= 0 && (r * y != x)) r++;
return r;
}
You can make use of the floorDiv function and fiddle with that:
int ceilDiv(int x, int y) {
return Math.floorDiv(x, y) + (x % y == 0 ? 0 : 1)
}

Mean of two ints (or longs) without overflow, truncating towards 0

I'd like a way to calculate (x + y)/2 for any two integers x, y in Java. The naive way suffers from issues if x+y > Integer.MAX_VALUE, or < Integer.MIN_VALUE.
Guava IntMath uses this technique:
public static int mean(int x, int y) {
// Efficient method for computing the arithmetic mean.
// The alternative (x + y) / 2 fails for large values.
// The alternative (x + y) >>> 1 fails for negative values.
return (x & y) + ((x ^ y) >> 1);
}
... but this rounds towards negative infinity, meaning the routine doesn't agree with the naive way for values like {-1, -2} (giving -2, rather than -1).
Is there any corresponding routine which truncates towards 0?
"Just use long" is not the answer I'm looking for, since I want a method that works for long inputs too. BigInteger is also not the answer I'm looking for. I don't want a solution with any branches.
You need to add 1 to the result if the lowest bits are different (so the result is not exact and you need to round), and the sign bit in the result is set (the result is negative, so you want to change the round down into a round up).
So the following should do (untested):
public static int mean(int x, int y) {
int xor = x ^ y;
int roundedDown = (x & y) + (xor >> 1);
return roundedDown + (1 & xor & (roundedDown >>> 31));
}
Why don't you do something like (x-y)/2 + y, which reduces to x/2 - y/2 + y = x/2 + y/2? So if x+y gives you an overflow or underflow, you do it the (x-y)/2 + y way.

Categories