What makes the following code print false? - java

public class Guess {
public static void main(String[] args){
<sometype> x = <somevalue>;
System.out.println(x == x);
}
}
i have to change sometype and somevalue so that it returns false? is it possible?

One:
float x = Float.NaN;
Two:
double x = 0.0/0.0;
Why?
As mentioned here already, NaN is never equal to another NaN - see http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html
So why this is not returning false?
Float x = Float.NaN;
The answer is that here, instead of a primitive assignment, there is a reference assignment. And there is a little auto boxing in the background. This is equal to:
Float x = new Float(Float.NaN);
Which is equal to:
Float x = new Float(0.0f / 0.0f);
Here x is a reference to a Float object, and the == operator tests reference equality, not value.
To see this returning false as well, the test should have been:
x.doubleValue()==x.doubleValue();
Which indeed returns false

Yes it is possible, you need to use:
// Edited for primitives :)
float x = Float.NaN;
// or
double x = Double.NaN;
This is because NaN is a special case that is not equal to itself.
From the JLS (4.2.3):
NaN is unordered, so the numerical comparison operators <, <=, >, and >= return false if either or both operands are NaN (§15.20.1). The equality operator == returns false if either operand is NaN, and the inequality operator != returns true if either operand is NaN (§15.21.1). In particular, x!=x is true if and only if x is NaN, and (x=y) will be false if x or y is NaN.

I can't think of any someType and someValue for which you could get x == x to come up false, sorry.
Update
Oh... yes, I think NAN is equal to nothing, even itself. So...
double and Double.NaN (or so).

This will print false:
!(x == x)
Other then that, it will only print false if you use NaN
float x = float.NaN;
Console.WriteLine(x == x);

Related

Comparing Scala and Java Double.NaN

Why does this comparison evaluate to true?
scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true
But this one evaluates to false?
scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false
aside: this interesting Twitter thread prompted me to ask this question
This is not about Scala's NaN vs. Java's -- there is only one NaN:
scala> val a = Double.NaN
a: Double = NaN
scala> val b = java.lang.Double.NaN
b: Double = NaN
Nor is it about there being two objects with the same value. It's about the definition of NaN. Two NaNs are not == because that's the way NaN is defined -- it is not a number, but rather a special value that means "undefined." If you have two of those, how would you know whether they are equal? For example:
scala> val x = 0.0 / 0.0
x: Double = NaN
scala> val y = Math.sqrt(-1)
y: Double = NaN
scala> x == y
res9: Boolean = false
Fortunately they are not ==; they are not numbers whose values you can compare.
As for x.equals(y), well, why would you do that in Scala? But given that you did, you are running into the bit of Java weirdness that I.K. pointed us to the docs for. Let's demonstrate it:
public class Foo {
public static void main( String[] args ) {
double nan1 = 0.0 / 0.0; Double box1 = nan1;
double nan2 = Math.sqrt(-1); Double box2 = nan2;
System.out.println( nan1 == nan2 ); // false, as expected
System.out.println( box1.equals(box2) ); // true -- WTF???
}
}
Double.NaN is the same as java.lang.Double.NaN, as AmigoNice already said. It's a Double (or double in Java terms). So using == on it is the same as == in Java and returns false for two NaNs, as expected. However, using equals forces the compiler to box both sides to java.lang.Double, and Double.equals is defined to return true in this case (which I just learned and which surprised me).
scala> Double.NaN equals java.lang.Double.NaN
res5: Boolean = true
This evaluates to true because Double.NaN is equivalent to java.lang.Double.NaN. Consequently, the equals method for java.lang.Double is called. According to the Java documentation, for two doubles, d1 and d2, if d1 and d2 both represent Double.NaN, then the equals method returns true, even though the value should be false according to IEEE specification.
scala> Double.NaN == java.lang.Double.NaN
res6: Boolean = false
This evaluates to false because Scala's == operator follows the IEEE specification. It does not call down to the Java == operator. Also, NaN is not a number as mentioned by #AmigoNico. It is a place holder for a large number of "invalid" values. There is no way of knowing whether two NaN's are equal, because they could be represented by two different "invalid" values.

Comparing doubles in Java gives odd results

I really can'get my head around why the following happens:
Double d = 0.0;
System.out.println(d == 0); // is true
System.out.println(d.equals(0)); // is false ?!
This however works as expected:
Double d = 0.0;
System.out.println(d == 0.0); // true
System.out.println(d.equals(0.0)); // true
I'm positive that this is related to autoboxing in some way, but I really don't know why 0 would be boxed differently when the == operator is used and when .equals is called.
Doesn't this implicitly violate the equals contract ?
* It is reflexive: for any non-null reference value
* x, x.equals(x) should return
* true.
EDIT:
Thanks for the fast answers. I figured that it is boxed differently, the real question is: why is it boxed differently ? I mean that this would be more intuitive if d == 0d than d.equals(0d) is intuitive and expected, however if d == 0 which looks like an Integer is true than 'intuitively' d.equals(0) should also be true.
just change it to
System.out.println(d.equals(0d)); // is false ?! now true
You were comparing double with Integer 0
Under the cover
System.out.println(d.equals(0)); // is false ?!
0 will be autoboxed to Integer and an instance of Integer will be passed to equals() method of Double class, where it will compare like
#Override
public boolean equals(Object object) {
return (object == this)
|| (object instanceof Double)
&& (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
}
which is going to return false of course.
Update
when you do comparison using == it compares values so there is no need to autobox , it directly operates on value. Where equals() accepts Object so if you try to invoke d1.equals(0) , 0 is not Object so it will perform autoboxing and it will pack it to Integer which is an Object.
Number objects only equal to numbers with the same value if they are of the same type. That is:
new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));
and similar combinations are all false.
In your case, the literal 0 is boxed into an Integer object.
It's probably worth noting that you should compare floating point numbers like this:
|x - y| < ε, ε very small
d.equals(0) : 0 is an int. The Double.equals() code will return true only for Double objects.
When you perform
d == 0
this is upcast to
d == 0.0
however there are no upcasting rules for autoboxing and even if there were equals(Object) gives no hits that you want a Double instead of an Integer.

Floating point rounding (in java)

What is the best way of determining if a given float(or double) has no significant decimal places.
f(234.0) = true
f(34.45) = false
f(3.1322) = false
i.e. equivalent of
EQ(((int)number) * 1.0 , number)
where EQ is a given method to compare floating points and it is OK to assume that the float fits in an integer.
Math.rint(x) == x
Math.rint() returns a double, so it also works for large numbers where the long result of Math.round() overflows.
Note that this also gives true for positive and negative infinity. You can explicitly exclude them by Math.rint(x) == x && !Double.isInfinite(x).
Round the value to the nearest integer, and calculate the absolute difference to the actual value.
If that difference is less than a certain percentage of the actual value you are close "enough".
You could try something like this:
public static boolean f(double d) {
return d % 1 == 0;
}

Why are these == but not `equals()`?

I'm a bit confused about the way Java treats == and equals() when it comes to int, Integer and other types of numbers. For example:
Integer X = 9000;
int x = 9000;
Short Y = 9000;
short y = 9000;
List<Boolean> results = new ArrayList<Boolean>();
// results.add(X == Y); DOES NOT COMPILE 1)
results.add(Y == 9000); // 2)
results.add(X == y); // 3)
results.add(X.equals(x)); // 4)
results.add(X.equals(Y)); // 5)
results.add(X.equals(y)); // 6)
System.out.println(results);
outputs (maybe you should make your guess first):
[true, true, true, false, false]
That X == Y does not compile is to be expected, being different objects.
I'm a little surprised that Y == 9 is true, given that 9 is by default an int, and given that 1) didn't even compile. Note that you can't put an int into a method expecting a Short, yet here they are equal.
This is surprising for the same reason as two, but it seems worse.
Not surprising, as x is autoboxed to and Integer.
Not surprising, as objects in different classes should not be equal().
What?? X == y is true but X.equals(y) is false? Shouldn't == always be stricter than equals()?
I'd appreciate it if anyone can help me make sense of this. For what reason do == and equals() behave this way?
Edit: I have changed 9 to 9000 to show that this behavior is not related to the any unusual ways that the integers from -128 to 127 behave.
2nd Edit: OK, if you think you understand this stuff, you should consider the following, just to make sure:
Integer X = 9000;
Integer Z = 9000;
short y = 9000;
List<Boolean> results = new ArrayList<Boolean>();
results.add(X == Z); // 1)
results.add(X == y); // 2)
results.add(X.equals(Z)); // 3)
results.add(X.equals(y)); // 4)
System.out.println(results);
outputs:
[false, true, true, false]
The reason, as best as I understand it:
Different instance, so different.
X unboxed, then same value, so equal.
Same value, so equal.
y cannot be boxed to an Integer so cannot be equal.
(small) Integer instances are cached, so the invariant x == y is holded for small instances (actually -127 +128, depends on JVM):
Integer a = 10;
Integer b = 10;
assert(a == b); // ok, same instance reused
a = 1024;
b = 1024;
assert(a == b); // fail, not the same instance....
assert(a.equals(b)); // but same _value_
EDIT
4) and 5) yield false because equals check types: X is an Integer whereas Y is a Short. This is the java.lang.Integer#equals method:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
The reason for
X == y
being true has to do with binary numeric promotion. When at least one operand to the equality operator is convertible to a numeric type, the numeric equality operator is used. First, the first operand is unboxed. Then, both operands are converted to int.
While
X.equals(y)
is a normal function call. As has been mentioned, y will be autoboxed to a Short object. Integer.equals always returns false if the argument is not an Integer instance. This can be easily seen by inspecting the implementation.
One could argue that this is a design flaw.
The morale of the story:
Autoboxing/unboxing is confusing, as is type promotion. Together, they make for good riddles but horrendous code.
In practice, it seldom makes sense to use numeric types smaller than int, and I'm almost inclined to configure my eclipse compiler to flag all autoboxing and -unboxing as an error.
Your problem here is not only how it treats == but autoboxing... When you compare Y and 9 you are comparing two primitives that are equal, in the last two cases you get false simply because that's how equals work. Two objects are equal only if they are of the same kind and have the same value.
When you say in "X.equals(y)" you are telling it to do Integer.equals(Short) and looking at the implementation of Integer.equals() it will fail:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Because of autoboxing the last two will result in the same failure as they will both be passed in as Shorts.
Edit: Forgot one thing... In the case of results.add(X == y); it will unbox X and do (X.intValue() == y) which happens to be true as well as 9 == 9
This automatic conversion is called autoboxing.
I remember a good practice for overriding "equal(object obj)" is of first checking the type of the parameter passed in. So perhap this causes X.equals(Y) to be false. You might check the souce code to dig out the truth :)
A bit more detail on how autoboxing works and how "small" valued Integer objects are cached:
When a primitive int is autoboxed into an Integer, the compiler does that by replacing the code with a call to Integer.valueOf(...). So, the following:
Integer a = 10;
is replaced by the compiler with the following:
Integer a = Integer.valueOf(10);
The valueOf(...) method of class Integer maintains a cache that contains Integer objects for all values between -127 and 128. If you call valueOf(...) with a value that's in this range, the method returns a pre-existing object from the cache. If the value is outside the range, it returns a new Integer object initialized with the specified value. (If you want to know exactly how it works, lookup the file src.zip in your JDK installation directory, and look for the source code of class java.lang.Integer in it.)
Now, if you do this:
Integer a = 10;
Integer b = 10;
System.out.println(a == b);
you'll see that true is printed - but not because a and b have the same value, but because a and b are referring to the same Integer object, the object from the cache returned by Integer.valueOf(...).
If you change the values:
Integer a = 200;
Integer b = 200;
System.out.println(a == b);
then false is printed, because 200 is outside the range of the cache, and so a and b refer to two distinct Integer objects.
It's unfortunate that == is used for object equality for value types such as the wrapper classes and String in Java - it's counter-intuitive.
Java will convert an Integer into an int automatically, if needed. Same applies to Short. This feature is called autoboxing and autounboxing. You can read about it here.
It means that when you run the code:
int a = 5;
Integer b = a;
System.out.println(a == b);
Java converts it into:
int a = 5;
Integer b = new Integer(a);
System.out.println(a == b.valueOf());

Confusing return statement

I'm failing to understand exactly what the IF statement is doing, from what I can see it is checking if the variable x is equal to the int 0. If this is true the ABSOLUTE value of the variable y is returned... this is when I lose the plot, why would the return statement then go on to include <= ESPILON? Surely this means less than or equal to the value of epsilon? if so how is that working? If it doesn't mean that then what does it mean?
(JAVA CODE)
final double EPSILON = 1E-14;
if (x == 0)
return Math.abs(y) <= EPSILON;
Floating-point math is by its nature inaccurate, so rather than testing for equivalence (which is always a bad idea), instead the developer has chosen a small number (1x10^-14 in this case) as the acceptable tolerance for proximity to zero. The return statement returns a comparison, so what this will do is take the absolute value of y, and return true if and only if it is sufficiently close to zero, where sufficiently close is defined by EPSILON.
It returns true if the absolute value of y is <= EPSILON, and false otherwise. The <= is evaluated before the return statement. This code is equivalent:
if(x == 0)
{
boolean ret = Math.abs(y) <= EPSILON;
return ret;
}
The code isn't simply read from left to right. A simpler example is
int x = 3 + 4 * 5;
After evaluating this, x is 23, not 35. The evaluation is 3 + (4*5), not (3+4)*5, because the * has a higher precedence than the +. The return statement in the original example has a very low precedence. All operators like +, -, <, >= are evaluated before it.
The entire expression
Math.abs(y) <= EPSILON
should be evaluated first, which means the function is going to return a boolean value (true/false). Having said that, if
x != 0
then I'm not sure what will get returned.
You're right that it is checking if the variable x is equal to (well, maybe int) 0. However, if this is true then it doesn't return the absolute value of y, it returns a boolean, the result of the <= operator.
It's returning a boolean value.
Epsilon is a double, holding the value 1E-14.
This is the actual IF statement
if (x==0) {
return MATH.abs(y) <= EPSILON;
}
So, what's getting returned is if the absolute value of y is less than or equals to Epsilon.
I haven't done Java in a long time but it would appear that this is actually returning a boolean (which might be implicitly cast).
I would say that if x equals 0, it returns true when the absolute value of y <= Epsilon, otherwise it returns false.
However if x doesn't equal 0 then it would return null, as no statement covers the else.
The "issue" is that this fragment relies heavyly on operator precedence (not bad per se, but sometimes it can be confusing).
Here you can find a list of all java operators with their precedence, and here for comparison the same table for C/C++
It is equivalent to this
return (Math.abs(y) <= EPSILON);
which should have been added to the code for clarity. As has been mentioned, it returns a boolean.
An alternatives would be
if (Math.abs(y) <= EPSILON)
return true;
else
return false;

Categories