How can "while (i == i) ;" be a non-infinite loop in a single threaded application?
JavaJava Problem Overview
I just got a question that I can't answer.
Suppose you have this loop definition in Java:
while (i == i) ;
What is the type of i
and the value of i
if the loop is not an infinite loop and the program is using only one thread?
Java Solutions
Solution 1 - Java
double i = Double.NaN;
The API for Double.equals() spells out the answer: "Double.NaN==Double.NaN has the value false". This is elaborated in the Java Language Specification under "Floating-Point Types, Formats, and Values":
> NaN
is unordered, so the numerical
> comparison operators <
, <=
, >
, and >=
> return false
if either or both
> operands are NaN
. The
> equality operator ==
returns false
if
> either operand is NaN
, and the
> inequality operator !=
returns true
if
> either operand is NaN
. In
> particular, x!=x
is true
if and only
> if x
is NaN
, and (x<y) == !(x>=y)
will
> be false
if x
or y
is NaN
.
Solution 2 - Java
The value of i
is then Invalid. "Not a Number".
After some googling, i found out that you CAN have NaN ( Not a Number ) in Java! So, a Float Pointing number is the Data Type and the Value is NaN. See here
Solution 3 - Java
double i = Double.NaN;
NaN is not equal to anything, including itself.
Solution 4 - Java
float i = Float.NaN;
while(i == i) ;
System.out.println("Not infinite!");
Solution 5 - Java
Since others said it's NaN I got curious about the official (JDK 6) implementation of Double.isNaN
, and behold:
/**
* Returns <code>true</code> if the specified number is a
* Not-a-Number (NaN) value, <code>false</code> otherwise.
*
* @param v the value to be tested.
* @return <code>true</code> if the value of the argument is NaN;
* <code>false</code> otherwise.
*/
static public boolean isNaN(double v) {
return (v != v);
}
Solution 6 - Java
I'm not sure, but I believe (i == i) is not atomic operation in multithreaded process, so if i value will be changed by other thread between pushes of it's value to stack on thread executing the loop, then that condition can be false.
Solution 7 - Java
I would add
float i = Float.NaN;
as well as
double i = Double.NaN;
A common trick in these sort of questions is in the assumption you make that i is an int. Other common assumptions might be s is a String, x,y are double, ch is a char, b is a byte etc. If you see a question like this you can bet that 'i' is not its expected type.
A similar question is; This never loops, what is 'x'
while(x == x && x != x + 0) { }
Another question I quite like is; This loop is an infinite loop, what are the possible values of x. (: I count four of them, as @Clement points out below :)
while(x != 0 && x == -x) { }
Solution 8 - Java
Think of Nan as the equivalent of exception but uses a magic value within a calculation. Because a calculation failed - eg square root of a negative, divide by zero etc - it makes no sense in comparing them against anything else. After all if divide by zero is a nan is it equivalent to the square root of -2 or square root of -3 ?
Nan allows a calculation that includes a step that returns an invalid answer to complete without introducing extra exceptions. To verify the answer is value simply test for non nandness ( is that's word if not I bags it) via Float.isNan() o equivalent.
Solution 9 - Java
I know this is a Java question, but considering the question for other languages is intriguing.
In C, a simple type such as 'int' could exhibit 'terminate before the universe grows cold' behaviour if 'i' was declared as a volatile (so the compiler would be forced to do two reads of 'i' for each iteration) and if 'i' was actually in memory where something else could affect it. Then the loop would terminate when 'i' changed between the two reads of a single iteration. (Added: a possible place - in a micro-computer where 'i' is actually located at the address of an I/O port, perhaps connected to a position sensor. It would be more plausible if 'i' was a pointer variable (a pointer to volatile memory) and the statement was 'while (*i == *i);
'.)
As evidenced by other answers, in C++, the '==' operator can be supplied by the user if i is of a user-defined class, so anything might be possible.
Rather like NaN, in an SQL-based language, the loop would not be infinite if the value of i was NULL; however, any non-NULL value would make the loop infinite. This is rather like Java, where any number (as opposed to NaN) makes the loop infinite.
I do not see the construct having any practical use, but it is an interesting trivia question.
Solution 10 - Java
I was surprised to not see this solution:
while (sin(x) == sin(x)) //probably won't eval to true
In response to a comment, try running this:
double x = 10.5f;
assert (x == asin(sin(x)));
x should always equal the arcsine(sin(x)) in theory, but in practice it doesn't.
Solution 11 - Java
Not infinite loop, one thread :)
import static B.*;
public class A {
public static void main(String[] args) {
System.out.println("Still Running");
while (i == i) ;
}
}
public class B {
public static int i;
static {
System.exit(0);
}
}
Solution 12 - Java
i == i
is not atomic. Proved by such program:
static volatile boolean i = true;
public static void main(String[] args) throws InterruptedException
{
new Thread() {
@Override
public void run() {
while (true) {
i = !i;
}
}
}.start();
while (i == i) ;
System.out.println("Not atomic! i: " + i);
}
Update Here is one more example of not-infinite loop (no new threads are created).
public class NoNewThreads {
public static void main(String[] args) {
new NoNewThreads();
System.gc();
int i = 500;
System.out.println("Still Running");
while (i == i) ;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
Thread.sleep(1000);
System.exit(0);
}
}