Comparison method violates its general contract, how to make it transitive? - java

I dont see how it is not transitive, please someone suggest me the right way.
if both values are null
I return 0, the two other statements are pretty obvious.
Why i got IllegalArgumentException with:
Comparison method violates its general contract
My compare method: (I compare doubles)
#Override
public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
double dist1 = 0;
double dist2 = 0;
int compInt1 = 0;
int compInt2 = 0;
if (lhs.get("dist") != null && rhs.get("dist") != null && !lhs.get("dist").equals("") && !rhs.get("dist").equals("")) {
dist1 = Double.parseDouble(lhs.get("dist").substring(0, lhs.get("dist").length() - 3));
dist2 = Double.parseDouble(rhs.get("dist").substring(0, rhs.get("dist").length() - 3));
dist1 = dist1 * 100;
dist2 = dist2 * 100;
compInt1 = (int) dist1;
compInt2 = (int) dist2;
}
if (compInt1 < compInt2) {
return -1;
} else if (compInt1 >= compInt2) {
return 1;
} else {
return 0;
}
}

Look at this code:
if (compInt1 < compInt2) {
return -1;
} else if (compInt1 >= compInt2) {
return 1;
} else {
return 0;
}
How do you expect that ever to return 0? What values of compInt1 and compInt2 would make both if conditions fail?
This violates symmetry too - it means that compare(x, y) and compare(y, x) can both return 1...
Assuming you're really just trying to compare compInt1 and compInt2 in the obvious way at this point, just replace the whole block with:
// As of Java 7...
return Integer.compare(compInt1, compInt2);
If you're using Java 6 (or earlier) you could use:
return Integer.valueOf(compInt1).compareTo(compInt2);
That's a little inefficient, but it's at least worth using to start with, just to get everything working.
Additionally, I'd strongly recommend extracting the lhs.get("dist") and rhs.get("dist") expressions from your first part - it's horribly repetitive at the moment. And just declare dist1 and dist2 within the block - they're not used elsewhere.

The condition else if (compInt1 >= compInt2) is ambiguous as it would return a value of 1 even if both values are equal. Replace your comparison logic of ints as follows :
return compInt1 - compInt2;

Transitivity defines as :
compare(a, b) == -compare(b, a)
Which implies compare(a, a) == -compare(a, a) == 0
Now, considering your code,
compare(a, a) == 1

Related

Comparison error for isometric sorting

So I'm implementing an isometric sorter for my sprites and I'm having some issues with the comparison of when the tiles should be rendered. I'm sorting all the isometric sprites that will be rendered by implementing them as comparable.
The problem is, when I'm implementing the following compareTo method:
// 1 = render this after
// 0 == render same
// -1 = render this before
#Override
public int compareTo(IsoSprite o) {
if(z >= o.z && maxY <= o.minY && maxX <= o.minX){
return 1;
}
if(z >= o.z && maxY >= o.minY && maxX >= o.minX){
return -1;
}
if(z > o.z){
return 1;
}
if(z < o.z){
return -1;
}
//z == o.z && maxY == o.maxY && minY == o.minY && minX == o.minX && maxX == o.maxX
return 0;
}
I get the error "Comparison method violates its general contract!" from the array.sort call in the LibGDX Array (which I use for sorting). I can't tell how I am supposed to solve this when looking at other peoples issue with this error, but those problems are mostly trivial. Anyone know how I should solve this in my isometric comparison?
My isometric world (for reference):
Edit:
Found something interesting when only sorting by Z:
//Doesn't work
public int compareTo(IsoSprite o) {
if(maxZ > o.z){
return 1;
}
if (maxZ < o.z){
return -1;
}
return 0;
}
//Works
#Override
public int compareTo(IsoSprite o) {
if(z > o.z){
return 1;
}
if(z < o.z){
return -1;
}
return 0;
}
I realised I won't be able to do the comparisons needed in a comparable. So instead I'm using my own implementation of Quicksort to sort using my own compareTo method that basically checks if a sprite is behind or infront of another one.
Thanks for all the help anyway!
This message indicates that there is something wrong
with transitive logic in comparator, for if A > B then also B < A must be true. The compiler is smart enough to point it out to the user.
The problem in code is that a different values are compared to each other. To correct it you have to compare the same values minY < o.minY, and not to use <= and >= operators.
This should work:
public int compareTo(IsoSprite o) {
if (isoDepth > o.isoDepth) return 1;
if (isoDepth < o.isoDepth) return -1;
return 0;
}
See algorithm to calculate isoDepth that could be used to sort /compare IsoSprites.

Why does this comparison method violate its general contract?

I am using a special comparator to sort a list of pairs according to the second part of the pair:
Collections.sort(ans, new Comparator<Pair<Component, Double>>()
{
public int compare(Pair<Component, Double> l, Pair<Component, Double> r)
{
if (r.second - l.second < 0) return -1;
else if(r.second==l.second) return 0;
else return 1;
}
});
The compare method seems to be both transitive (a < b < c => a < c) and each component
is equal to itself. What could cause the exception?
There are edge cases you haven't considered—and shouldn't, because the JDK already provides a fully compliant method, which I present here for completeness::
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}

Exception during Collections.sort()

A java.lang.IllegalArgumentException: Comparison method violates its general contract! is thrown when I do a Collections.sort() with a List of ISimulationResultSet.
I have not found the reason why contract is not respected.
If someone has a idea of the reason, it will be great to explain.
This is the Comparator I am using :
public int compare(ISimulationResultSet r1, ISimulationResultSet r2) {
final float r1Esperance = r1.getResults().getEsperanceGainOuPerte();
final float r2Esperance = r2.getResults().getEsperanceGainOuPerte();
final float r1PrctCibleAtteinte = r1.getResults().getPrctCibleAtteinte();
final float r2PrctCibleAtteinte = r2.getResults().getPrctCibleAtteinte();
if (r1Esperance / r2Esperance > 1.05F)
return -1;
else if (r1Esperance / r2Esperance < 0.95F) {
return 1;
}
else {
if (r1PrctCibleAtteinte == r2PrctCibleAtteinte) {
if (r1Esperance > r2Esperance)
return -1;
else if (r1Esperance < r2Esperance)
return 1;
return 0;
}
else if (r1PrctCibleAtteinte > r2PrctCibleAtteinte)
return -1;
else if (r1PrctCibleAtteinte < r2PrctCibleAtteinte)
return 1;
}
return 0;
}
The comparator has to be symetric, i.e. sgn(compare(x, y)) == -sgn(compare(y, x)) (sgn being the signum function here). This is not the case for your comparator:
Let a1 and a2 denote the values of x.getResults().getEsperanceGainOuPerte() and y.getResults().getEsperanceGainOuPerte() respectively and let b1 and b2 denote the values of x.getResults().getPrctCibleAtteinte() and y.getResults().getPrctCibleAtteinte() respectively.
Now consider the following:
1.05 < a1 < 1.052
a2 = 1
b2 > b1
Therefore a2 / a1 > 0.95
compare(x, y) == -1;// first (r1Esperance / r2Esperance > 1.05F) is true
compare(y, x) == -1; // first 3 conditions false, (r1PrctCibleAtteinte > r2PrctCibleAtteinte) is true
That violates the contract.

Java boolean method needs extra return statement?

I am starting with java and while I was writing a way to identify whether a number was prime I wrote a method like this
public static boolean checkPrime(int n){
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !Prime;
}
else if(((n % x) == 0) && (n > x)){
return Prime;
}
else {
return Prime;
}
}
What I couldn't figure out was the necessity of the last else statement. If I do not put it, I get an error message. However I don't think it is necessary since all possibilities are covered by the previous loops, with their respecting return statements. Or am I missing something?
You don't need the else. What you are being told by the compiler is the method must return SOMETHING. Your last else block could replaced by this:
return PrimeOrNot;
In fact, your method could look like this:
public static boolean checkPrime(int n){
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !(PrimeOrNot);
}
return (PrimeOrNot);
}
In any case your very last statement block cannot be an else if.
The method has a return type of boolean.
The compiler is scared by the possibility in which none of the 'if' cases are met. In this situation, the method know what to return. This method needs to return something, so just give it a 'return true' before the method ends. It won't ever be read, but it will make the compiler happy.
The conditional expressions within the if/else-if are only evaluated at runtime. Normally, the compiler wouldn't know what the result would be, because they are not evaluated at compile-time. Only, situation when the compiler can figure what the result of the expression would be is when it's some compile-time constant (like if(true) {).
public static boolean checkPrime(int n){
boolean PrimeOrNot = false;
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !(PrimeOrNot);
}
else if(((n % x) == 0) && (n > x)){
return (PrimeOrNot);
}
return PrimeOrNot;
}
A method which returns a value will be compilable if it returns a value in all its possible code paths.
Imagine for a moment that you're the compiler. You see this code:
int myMethod()
{
if (cond)
return anInt;
}
While you may know that cond is in fact always true, the compiler will not know that. It can only be sure about the result of a boolean expression if it is an expression which can be evaluated at compile time only.
Note that the vast majority of "code optimization" in Java is in fact done at run time (JIT: Just In Time).
The compiler only checks to see if there are valid return paths from your method. The compiler isn't "smart" enough to inspect the conditional statements and determine whether the conditions can be logically met -- the compiler simply checks to make sure that some value is returned to respect the contract of the method declaration.
Some would argue that the following is a cleaner structure for the method (but I think it is just a matter of taste):
public static boolean checkPrime(int n){
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !(PrimeOrNot);
}
return (PrimeOrNot);
}

How to determine if a number is positive or negative?

I was asked in an interview, how to determine whether a number is positive or negative. The rules are that we should not use relational operators such as <, and >, built in java functions (like substring, indexOf, charAt, and startsWith), no regex, or API's.
I did some homework on this and the code is given below, but it only works for integer type. But they asked me to write a generic code that works for float, double, and long.
// This might not be better way!!
S.O.P ((( number >> 31 ) & 1) == 1 ? "- ve number " : "+ve number );
any ideas from your side?
The integer cases are easy. The double case is trickier, until you remember about infinities.
Note: If you consider the double constants "part of the api", you can replace them with overflowing expressions like 1E308 * 2.
int sign(int i) {
if (i == 0) return 0;
if (i >> 31 != 0) return -1;
return +1;
}
int sign(long i) {
if (i == 0) return 0;
if (i >> 63 != 0) return -1;
return +1;
}
int sign(double f) {
if (f != f) throw new IllegalArgumentException("NaN");
if (f == 0) return 0;
f *= Double.POSITIVE_INFINITY;
if (f == Double.POSITIVE_INFINITY) return +1;
if (f == Double.NEGATIVE_INFINITY) return -1;
//this should never be reached, but I've been wrong before...
throw new IllegalArgumentException("Unfathomed double");
}
The following is a terrible approach that would get you fired at any job...
It depends on you getting a Stack Overflow Exception [or whatever Java calls it]... And it would only work for positive numbers that don't deviate from 0 like crazy.
Negative numbers are fine, since you would overflow to positive, and then get a stack overflow exception eventually [which would return false, or "yes, it is negative"]
Boolean isPositive<T>(T a)
{
if(a == 0) return true;
else
{
try
{
return isPositive(a-1);
}catch(StackOverflowException e)
{
return false; //It went way down there and eventually went kaboom
}
}
}
This will only works for everything except [0..2]
boolean isPositive = (n % (n - 1)) * n == n;
You can make a better solution like this (works except for [0..1])
boolean isPositive = ((n % (n - 0.5)) * n) / 0.5 == n;
You can get better precision by changing the 0.5 part with something like 2^m (m integer):
boolean isPositive = ((n % (n - 0.03125)) * n) / 0.03125 == n;
You can do something like this:
((long) (num * 1E308 * 1E308) >> 63) == 0 ? "+ve" : "-ve"
The main idea here is that we cast to a long and check the value of the most significant bit. As a double/float between -1 and 0 will round to zero when cast to a long, we multiply by large doubles so that a negative float/double will be less than -1. Two multiplications are required because of the existence of subnormals (it doesn't really need to be that big though).
What about this?
return ((num + "").charAt(0) == '-');
// Returns 0 if positive, nonzero if negative
public long sign(long value) {
return value & 0x8000000000000000L;
}
Call like:
long val1 = ...;
double val2 = ...;
float val3 = ...;
int val4 = ...;
sign((long) valN);
Casting from double / float / integer to long should preserve the sign, if not the actual value...
You say
we should not use conditional operators
But this is a trick requirement, because == is also a conditional operator. There is also one built into ? :, while, and for loops. So nearly everyone has failed to provide an answer meeting all the requirements.
The only way to build a solution without a conditional operator is to use lookup table vs one of a few other people's solutions that can be boiled down to 0/1 or a character, before a conditional is met.
Here are the answers that I think might work vs a lookup table:
Nabb
Steven Schlansker
Dennis Cheung
Gary Rowe
This solution uses modulus. And yes, it also works for 0.5 (tests are below, in the main method).
public class Num {
public static int sign(long x) {
if (x == 0L || x == 1L) return (int) x;
return x == Long.MIN_VALUE || x % (x - 1L) == x ? -1 : 1;
}
public static int sign(double x) {
if (x != x) throw new IllegalArgumentException("NaN");
if (x == 0.d || x == 1.d) return (int) x;
if (x == Double.POSITIVE_INFINITY) return 1;
if (x == Double.NEGATIVE_INFINITY) return -1;
return x % (x - 1.d) == x ? -1 : 1;
}
public static int sign(int x) {
return Num.sign((long)x);
}
public static int sign(float x) {
return Num.sign((double)x);
}
public static void main(String args[]) {
System.out.println(Num.sign(Integer.MAX_VALUE)); // 1
System.out.println(Num.sign(1)); // 1
System.out.println(Num.sign(0)); // 0
System.out.println(Num.sign(-1)); // -1
System.out.println(Num.sign(Integer.MIN_VALUE)); // -1
System.out.println(Num.sign(Long.MAX_VALUE)); // 1
System.out.println(Num.sign(1L)); // 1
System.out.println(Num.sign(0L)); // 0
System.out.println(Num.sign(-1L)); // -1
System.out.println(Num.sign(Long.MIN_VALUE)); // -1
System.out.println(Num.sign(Double.POSITIVE_INFINITY)); // 1
System.out.println(Num.sign(Double.MAX_VALUE)); // 1
System.out.println(Num.sign(0.5d)); // 1
System.out.println(Num.sign(0.d)); // 0
System.out.println(Num.sign(-0.5d)); // -1
System.out.println(Num.sign(Double.MIN_VALUE)); // -1
System.out.println(Num.sign(Double.NEGATIVE_INFINITY)); // -1
System.out.println(Num.sign(Float.POSITIVE_INFINITY)); // 1
System.out.println(Num.sign(Float.MAX_VALUE)); // 1
System.out.println(Num.sign(0.5f)); // 1
System.out.println(Num.sign(0.f)); // 0
System.out.println(Num.sign(-0.5f)); // -1
System.out.println(Num.sign(Float.MIN_VALUE)); // -1
System.out.println(Num.sign(Float.NEGATIVE_INFINITY)); // -1
System.out.println(Num.sign(Float.NaN)); // Throws an exception
}
}
This code covers all cases and types:
public static boolean isNegative(Number number) {
return (Double.doubleToLongBits(number.doubleValue()) & Long.MIN_VALUE) == Long.MIN_VALUE;
}
This method accepts any of the wrapper classes (Integer, Long, Float and Double) and thanks to auto-boxing any of the primitive numeric types (int, long, float and double) and simply checks it the high bit, which in all types is the sign bit, is set.
It returns true when passed any of:
any negative int/Integer
any negative long/Long
any negative float/Float
any negative double/Double
Double.NEGATIVE_INFINITY
Float.NEGATIVE_INFINITY
and false otherwise.
Untested, but illustrating my idea:
boolean IsNegative<T>(T v) {
return (v & ((T)-1));
}
It seems arbitrary to me because I don't know how you would get the number as any type, but what about checking Abs(number) != number? Maybe && number != 0
Integers are trivial; this you already know. The deep problem is how to deal with floating-point values. At that point, you've got to know a bit more about how floating point values actually work.
The key is Double.doubleToLongBits(), which lets you get at the IEEE representation of the number. (The method's really a direct cast under the hood, with a bit of magic for dealing with NaN values.) Once a double has been converted to a long, you can just use 0x8000000000000000L as a mask to select the sign bit; if zero, the value is positive, and if one, it's negative.
If it is a valid answer
boolean IsNegative(char[] v) throws NullPointerException, ArrayIndexOutOfBoundException
{
return v[0]=='-';
}
one more option I could think of
private static boolean isPositive(Object numberObject) {
Long number = Long.valueOf(numberObject.toString());
return Math.sqrt((number * number)) != number;
}
private static boolean isPositive(Object numberObject) {
Long number = Long.valueOf(numberObject.toString());
long signedLeftShifteredNumber = number << 1; // Signed left shift
long unsignedRightShifterNumber = signedLeftShifteredNumber >>> 1; // Unsigned right shift
return unsignedRightShifterNumber == number;
}
This one is roughly based on ItzWarty's answer, but it runs in logn time! Caveat: Only works for integers.
Boolean isPositive(int a)
{
if(a == -1) return false;
if(a == 0) return false;
if(a == 1) return true;
return isPositive(a/2);
}
I think there is a very simple solution:
public boolean isPositive(int|float|double|long i){
return (((i-i)==0)? true : false);
}
tell me if I'm wrong!
Try this without the code: (x-SQRT(x^2))/(2*x)
Write it using the conditional then take a look at the assembly code generated.
Why not get the square root of the number? If its negative - java will throw an error and we will handle it.
try {
d = Math.sqrt(THE_NUMBER);
}
catch ( ArithmeticException e ) {
console.putln("Number is negative.");
}
I don't know how exactly Java coerces numeric values, but the answer is pretty simple, if put in pseudocode (I leave the details to you):
sign(x) := (x == 0) ? 0 : (x/x)
If you are allowed to use "==" as seems to be the case, you can do something like that taking advantage of the fact that an exception will be raised if an array index is out of bounds. The code is for double, but you can cast any numeric type to a double (here the eventual loss of precision would not be important at all).
I have added comments to explain the process (bring the value in ]-2.0; -1.0] union [1.0; 2.0[) and a small test driver as well.
class T {
public static boolean positive(double f)
{
final boolean pos0[] = {true};
final boolean posn[] = {false, true};
if (f == 0.0)
return true;
while (true) {
// If f is in ]-1.0; 1.0[, multiply it by 2 and restart.
try {
if (pos0[(int) f]) {
f *= 2.0;
continue;
}
} catch (Exception e) {
}
// If f is in ]-2.0; -1.0] U [1.0; 2.0[, return the proper answer.
try {
return posn[(int) ((f+1.5)/2)];
} catch (Exception e) {
}
// f is outside ]-2.0; 2.0[, divide by 2 and restart.
f /= 2.0;
}
}
static void check(double f)
{
System.out.println(f + " -> " + positive(f));
}
public static void main(String args[])
{
for (double i = -10.0; i <= 10.0; i++)
check(i);
check(-1e24);
check(-1e-24);
check(1e-24);
check(1e24);
}
The output is:
-10.0 -> false
-9.0 -> false
-8.0 -> false
-7.0 -> false
-6.0 -> false
-5.0 -> false
-4.0 -> false
-3.0 -> false
-2.0 -> false
-1.0 -> false
0.0 -> true
1.0 -> true
2.0 -> true
3.0 -> true
4.0 -> true
5.0 -> true
6.0 -> true
7.0 -> true
8.0 -> true
9.0 -> true
10.0 -> true
-1.0E24 -> false
-1.0E-24 -> false
1.0E-24 -> true
1.0E24 -> true
Well, taking advantage of casting (since we don't care what the actual value is) perhaps the following would work. Bear in mind that the actual implementations do not violate the API rules. I've edited this to make the method names a bit more obvious and in light of #chris' comment about the {-1,+1} problem domain. Essentially, this problem does not appear to solvable without recourse to API methods within Float or Double that reference the native bit structure of the float and double primitives.
As everybody else has said: Stupid interview question. Grr.
public class SignDemo {
public static boolean isNegative(byte x) {
return (( x >> 7 ) & 1) == 1;
}
public static boolean isNegative(short x) {
return (( x >> 15 ) & 1) == 1;
}
public static boolean isNegative(int x) {
return (( x >> 31 ) & 1) == 1;
}
public static boolean isNegative(long x) {
return (( x >> 63 ) & 1) == 1;
}
public static boolean isNegative(float x) {
return isNegative((int)x);
}
public static boolean isNegative(double x) {
return isNegative((long)x);
}
public static void main(String[] args) {
// byte
System.out.printf("Byte %b%n",isNegative((byte)1));
System.out.printf("Byte %b%n",isNegative((byte)-1));
// short
System.out.printf("Short %b%n",isNegative((short)1));
System.out.printf("Short %b%n",isNegative((short)-1));
// int
System.out.printf("Int %b%n",isNegative(1));
System.out.printf("Int %b%n",isNegative(-1));
// long
System.out.printf("Long %b%n",isNegative(1L));
System.out.printf("Long %b%n",isNegative(-1L));
// float
System.out.printf("Float %b%n",isNegative(Float.MAX_VALUE));
System.out.printf("Float %b%n",isNegative(Float.NEGATIVE_INFINITY));
// double
System.out.printf("Double %b%n",isNegative(Double.MAX_VALUE));
System.out.printf("Double %b%n",isNegative(Double.NEGATIVE_INFINITY));
// interesting cases
// This will fail because we can't get to the float bits without an API and
// casting will round to zero
System.out.printf("{-1,1} (fail) %b%n",isNegative(-0.5f));
}
}
This solution uses no conditional operators, but relies on catching two excpetions.
A division error equates to the number originally being "negative". Alternatively, the number will eventually fall off the planet and throw a StackOverFlow exception if it is positive.
public static boolean isPositive( f)
{
int x;
try {
x = 1/((int)f + 1);
return isPositive(x+1);
} catch (StackOverFlow Error e) {
return true;
} catch (Zero Division Error e) {
return false;
}
}
What about the following?
T sign(T x) {
if(x==0) return 0;
return x/Math.abs(x);
}
Should work for every type T...
Alternatively, one can define abs(x) as Math.sqrt(x*x),
and if that is also cheating, implement your own square root function...
if (((Double)calcYourDouble()).toString().contains("-"))
doThis();
else doThat();
Combined generics with double API. Guess it's a bit of cheating, but at least we need to write only one method:
static <T extends Number> boolean isNegative(T number)
{
return ((number.doubleValue() * Double.POSITIVE_INFINITY) == Double.NEGATIVE_INFINITY);
}
Two simple solutions. Works also for infinities and numbers -1 <= r <= 1
Will return "positive" for NaNs.
String positiveOrNegative(double number){
return (((int)(number/0.0))>>31 == 0)? "positive" : "negative";
}
String positiveOrNegative(double number){
return (number==0 || ((int)(number-1.0))>>31==0)? "positive" : "negative";
}
There is a function is the math library called signnum.
http://www.tutorialspoint.com/java/lang/math_signum_float.htm
http://www.tutorialspoint.com/java/lang/math_signum_double.htm
It's easy to do this like
private static boolean isNeg(T l) {
return (Math.abs(l-1)>Math.abs(l));
}
static boolean isNegative(double v) {
return new Double(v).toString().startsWith("-");
}

Categories

Resources