For what value of i does while (i == i + 1) {} loop forever?
up vote
94
down vote
favorite
I ran cross this puzzler from an advanced programming course at a UK university exam.
Consider the following loop, in which i is, so far, undeclared:
while (i == i + 1) {}
Find the definition of i
, that precedes this loop, such that the while loop
continues for ever.
The next question, which asked the same question for this code snippet:
while (i != i) {}
was obvious to me. Of course in this other situation it is NaN
but I am really stuck on the prior one. Does this have to do with overflow? What would cause such a loop to loop for ever in Java?
java loops types
|
show 11 more comments
up vote
94
down vote
favorite
I ran cross this puzzler from an advanced programming course at a UK university exam.
Consider the following loop, in which i is, so far, undeclared:
while (i == i + 1) {}
Find the definition of i
, that precedes this loop, such that the while loop
continues for ever.
The next question, which asked the same question for this code snippet:
while (i != i) {}
was obvious to me. Of course in this other situation it is NaN
but I am really stuck on the prior one. Does this have to do with overflow? What would cause such a loop to loop for ever in Java?
java loops types
3
Any possibilities to override.equals()
method? Since i is undeclared, we may use any class of what we want.
– Geno Chen
Nov 28 at 9:35
7
@Raedwald studying "unprofessional" code makes you more "professional", so... Anyway, it's a good question
– Andrew Tobilko
Nov 28 at 9:56
11
Fun fact, in C# this also works for nullable numeric types whose values arenull
, sincenull == null
is true, andnull + 1
isnull
.
– Eric Lippert
Nov 28 at 15:38
3
@EricDuminil: The situation is far worse than you imagine. In many languages, floating point arithmetic must be done in at least the 64 bits of precision specified by a double, which means that it can be done in higher precision at the whim of the compiler, and in practice this happens. I can point you at a dozen questions on this site from C# programmers who are wondering why0.2 + 0.1 == 0.3
changes its value depending on compiler settings, the phase of the moon, and so on.
– Eric Lippert
Nov 28 at 23:38
5
@EricDuminil: The blame for this mess falls on Intel, who gave us a chip set that does higher-precision and faster floating point arithmetic if the numbers can be enregistered, which means that the results of a floating point computation can change their values depending on how well the register scheduler in the optimizer works today. Your choices as a language designer are then between repeatable computations and fast, precise computations, and the community that cares about floating point math will opt for the latter.
– Eric Lippert
Nov 28 at 23:41
|
show 11 more comments
up vote
94
down vote
favorite
up vote
94
down vote
favorite
I ran cross this puzzler from an advanced programming course at a UK university exam.
Consider the following loop, in which i is, so far, undeclared:
while (i == i + 1) {}
Find the definition of i
, that precedes this loop, such that the while loop
continues for ever.
The next question, which asked the same question for this code snippet:
while (i != i) {}
was obvious to me. Of course in this other situation it is NaN
but I am really stuck on the prior one. Does this have to do with overflow? What would cause such a loop to loop for ever in Java?
java loops types
I ran cross this puzzler from an advanced programming course at a UK university exam.
Consider the following loop, in which i is, so far, undeclared:
while (i == i + 1) {}
Find the definition of i
, that precedes this loop, such that the while loop
continues for ever.
The next question, which asked the same question for this code snippet:
while (i != i) {}
was obvious to me. Of course in this other situation it is NaN
but I am really stuck on the prior one. Does this have to do with overflow? What would cause such a loop to loop for ever in Java?
java loops types
java loops types
edited Nov 29 at 11:28
Oleksandr
8,56043768
8,56043768
asked Nov 28 at 9:31
jake mckenzie
60157
60157
3
Any possibilities to override.equals()
method? Since i is undeclared, we may use any class of what we want.
– Geno Chen
Nov 28 at 9:35
7
@Raedwald studying "unprofessional" code makes you more "professional", so... Anyway, it's a good question
– Andrew Tobilko
Nov 28 at 9:56
11
Fun fact, in C# this also works for nullable numeric types whose values arenull
, sincenull == null
is true, andnull + 1
isnull
.
– Eric Lippert
Nov 28 at 15:38
3
@EricDuminil: The situation is far worse than you imagine. In many languages, floating point arithmetic must be done in at least the 64 bits of precision specified by a double, which means that it can be done in higher precision at the whim of the compiler, and in practice this happens. I can point you at a dozen questions on this site from C# programmers who are wondering why0.2 + 0.1 == 0.3
changes its value depending on compiler settings, the phase of the moon, and so on.
– Eric Lippert
Nov 28 at 23:38
5
@EricDuminil: The blame for this mess falls on Intel, who gave us a chip set that does higher-precision and faster floating point arithmetic if the numbers can be enregistered, which means that the results of a floating point computation can change their values depending on how well the register scheduler in the optimizer works today. Your choices as a language designer are then between repeatable computations and fast, precise computations, and the community that cares about floating point math will opt for the latter.
– Eric Lippert
Nov 28 at 23:41
|
show 11 more comments
3
Any possibilities to override.equals()
method? Since i is undeclared, we may use any class of what we want.
– Geno Chen
Nov 28 at 9:35
7
@Raedwald studying "unprofessional" code makes you more "professional", so... Anyway, it's a good question
– Andrew Tobilko
Nov 28 at 9:56
11
Fun fact, in C# this also works for nullable numeric types whose values arenull
, sincenull == null
is true, andnull + 1
isnull
.
– Eric Lippert
Nov 28 at 15:38
3
@EricDuminil: The situation is far worse than you imagine. In many languages, floating point arithmetic must be done in at least the 64 bits of precision specified by a double, which means that it can be done in higher precision at the whim of the compiler, and in practice this happens. I can point you at a dozen questions on this site from C# programmers who are wondering why0.2 + 0.1 == 0.3
changes its value depending on compiler settings, the phase of the moon, and so on.
– Eric Lippert
Nov 28 at 23:38
5
@EricDuminil: The blame for this mess falls on Intel, who gave us a chip set that does higher-precision and faster floating point arithmetic if the numbers can be enregistered, which means that the results of a floating point computation can change their values depending on how well the register scheduler in the optimizer works today. Your choices as a language designer are then between repeatable computations and fast, precise computations, and the community that cares about floating point math will opt for the latter.
– Eric Lippert
Nov 28 at 23:41
3
3
Any possibilities to override
.equals()
method? Since i is undeclared, we may use any class of what we want.– Geno Chen
Nov 28 at 9:35
Any possibilities to override
.equals()
method? Since i is undeclared, we may use any class of what we want.– Geno Chen
Nov 28 at 9:35
7
7
@Raedwald studying "unprofessional" code makes you more "professional", so... Anyway, it's a good question
– Andrew Tobilko
Nov 28 at 9:56
@Raedwald studying "unprofessional" code makes you more "professional", so... Anyway, it's a good question
– Andrew Tobilko
Nov 28 at 9:56
11
11
Fun fact, in C# this also works for nullable numeric types whose values are
null
, since null == null
is true, and null + 1
is null
.– Eric Lippert
Nov 28 at 15:38
Fun fact, in C# this also works for nullable numeric types whose values are
null
, since null == null
is true, and null + 1
is null
.– Eric Lippert
Nov 28 at 15:38
3
3
@EricDuminil: The situation is far worse than you imagine. In many languages, floating point arithmetic must be done in at least the 64 bits of precision specified by a double, which means that it can be done in higher precision at the whim of the compiler, and in practice this happens. I can point you at a dozen questions on this site from C# programmers who are wondering why
0.2 + 0.1 == 0.3
changes its value depending on compiler settings, the phase of the moon, and so on.– Eric Lippert
Nov 28 at 23:38
@EricDuminil: The situation is far worse than you imagine. In many languages, floating point arithmetic must be done in at least the 64 bits of precision specified by a double, which means that it can be done in higher precision at the whim of the compiler, and in practice this happens. I can point you at a dozen questions on this site from C# programmers who are wondering why
0.2 + 0.1 == 0.3
changes its value depending on compiler settings, the phase of the moon, and so on.– Eric Lippert
Nov 28 at 23:38
5
5
@EricDuminil: The blame for this mess falls on Intel, who gave us a chip set that does higher-precision and faster floating point arithmetic if the numbers can be enregistered, which means that the results of a floating point computation can change their values depending on how well the register scheduler in the optimizer works today. Your choices as a language designer are then between repeatable computations and fast, precise computations, and the community that cares about floating point math will opt for the latter.
– Eric Lippert
Nov 28 at 23:41
@EricDuminil: The blame for this mess falls on Intel, who gave us a chip set that does higher-precision and faster floating point arithmetic if the numbers can be enregistered, which means that the results of a floating point computation can change their values depending on how well the register scheduler in the optimizer works today. Your choices as a language designer are then between repeatable computations and fast, precise computations, and the community that cares about floating point math will opt for the latter.
– Eric Lippert
Nov 28 at 23:41
|
show 11 more comments
3 Answers
3
active
oldest
votes
up vote
123
down vote
accepted
First of all, since the while (i == i + 1) {}
loop doesn't change the value of i
, making this loop infinite is equivalent to choosing a value of i
that satisfies i == i + 1
.
There are many such values:
Let's start with the "exotic" ones:
double i = Double.POSITIVE_INFINITY;
or
double i = Double.NEGATIVE_INFINITY;
The reason for these values satisfying i == i + 1
is stated in
JLS 15.18.2. Additive Operators (+ and -) for Numeric Types:
The sum of an infinity and a finite value is equal to the infinite operand.
This is not surprising, since adding a finite value to an infinite value should result in an infinite value.
That said, most of the values of i
that satisfy i == i + 1
are simply large double
(or float
) values:
For example:
double i = Double.MAX_VALUE;
or
double i = 1000000000000000000.0;
or
float i = 1000000000000000000.0f;
The double
and float
types have limited precision, so if you take a large enough double
or float
value, adding 1
to it will result in the same value.
9
Or(double)(1L<<53)
-- orfloat i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
3
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
2
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
3
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
2
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
|
show 11 more comments
up vote
57
down vote
These puzzles are described in detail in the "Java Puzzlers: Traps, Pitfalls, and Corner Cases" book by Joshua Bloch and Neal Gafter.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
or:
double i = 1.0e40;
while (i == i + 1) {}
both will result in an infinite loop, because adding 1
to a floating-point value that is sufficiently large will not change the value, because it doesn't "bridge the gap" to its successor1.
A note about the second puzzle (for future readers):
double i = Double.NaN;
while (i != i) {}
also results in an infinite loop, because NaN is not equal to any floating-point value, including itself 2.
1 - Java Puzzlers: Traps, Pitfalls, and Corner Cases (chapter 4 - Loopy Puzzlers).
2 - JLS §15.21.1
7
There should be a seperate hell for everyone that usesi
as a non integer variable. Or a as a counter at all... Not your fault I know...
– Kami Kaze
Nov 29 at 8:56
@KamiKaze Especially since several high-level languages havei
defined assqrt(-1)
by default and you end up overloading -- actually overriding -- this value.
– Carl Witthoft
Nov 29 at 16:10
add a comment |
up vote
1
down vote
Just an idea: what about booleans?
bool i = TRUE;
Isn't this a case where i + 1 == i
?
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
5
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no+
operator that takes aboolean
and anint
as operands).
– Eran
Nov 30 at 9:05
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
123
down vote
accepted
First of all, since the while (i == i + 1) {}
loop doesn't change the value of i
, making this loop infinite is equivalent to choosing a value of i
that satisfies i == i + 1
.
There are many such values:
Let's start with the "exotic" ones:
double i = Double.POSITIVE_INFINITY;
or
double i = Double.NEGATIVE_INFINITY;
The reason for these values satisfying i == i + 1
is stated in
JLS 15.18.2. Additive Operators (+ and -) for Numeric Types:
The sum of an infinity and a finite value is equal to the infinite operand.
This is not surprising, since adding a finite value to an infinite value should result in an infinite value.
That said, most of the values of i
that satisfy i == i + 1
are simply large double
(or float
) values:
For example:
double i = Double.MAX_VALUE;
or
double i = 1000000000000000000.0;
or
float i = 1000000000000000000.0f;
The double
and float
types have limited precision, so if you take a large enough double
or float
value, adding 1
to it will result in the same value.
9
Or(double)(1L<<53)
-- orfloat i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
3
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
2
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
3
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
2
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
|
show 11 more comments
up vote
123
down vote
accepted
First of all, since the while (i == i + 1) {}
loop doesn't change the value of i
, making this loop infinite is equivalent to choosing a value of i
that satisfies i == i + 1
.
There are many such values:
Let's start with the "exotic" ones:
double i = Double.POSITIVE_INFINITY;
or
double i = Double.NEGATIVE_INFINITY;
The reason for these values satisfying i == i + 1
is stated in
JLS 15.18.2. Additive Operators (+ and -) for Numeric Types:
The sum of an infinity and a finite value is equal to the infinite operand.
This is not surprising, since adding a finite value to an infinite value should result in an infinite value.
That said, most of the values of i
that satisfy i == i + 1
are simply large double
(or float
) values:
For example:
double i = Double.MAX_VALUE;
or
double i = 1000000000000000000.0;
or
float i = 1000000000000000000.0f;
The double
and float
types have limited precision, so if you take a large enough double
or float
value, adding 1
to it will result in the same value.
9
Or(double)(1L<<53)
-- orfloat i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
3
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
2
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
3
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
2
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
|
show 11 more comments
up vote
123
down vote
accepted
up vote
123
down vote
accepted
First of all, since the while (i == i + 1) {}
loop doesn't change the value of i
, making this loop infinite is equivalent to choosing a value of i
that satisfies i == i + 1
.
There are many such values:
Let's start with the "exotic" ones:
double i = Double.POSITIVE_INFINITY;
or
double i = Double.NEGATIVE_INFINITY;
The reason for these values satisfying i == i + 1
is stated in
JLS 15.18.2. Additive Operators (+ and -) for Numeric Types:
The sum of an infinity and a finite value is equal to the infinite operand.
This is not surprising, since adding a finite value to an infinite value should result in an infinite value.
That said, most of the values of i
that satisfy i == i + 1
are simply large double
(or float
) values:
For example:
double i = Double.MAX_VALUE;
or
double i = 1000000000000000000.0;
or
float i = 1000000000000000000.0f;
The double
and float
types have limited precision, so if you take a large enough double
or float
value, adding 1
to it will result in the same value.
First of all, since the while (i == i + 1) {}
loop doesn't change the value of i
, making this loop infinite is equivalent to choosing a value of i
that satisfies i == i + 1
.
There are many such values:
Let's start with the "exotic" ones:
double i = Double.POSITIVE_INFINITY;
or
double i = Double.NEGATIVE_INFINITY;
The reason for these values satisfying i == i + 1
is stated in
JLS 15.18.2. Additive Operators (+ and -) for Numeric Types:
The sum of an infinity and a finite value is equal to the infinite operand.
This is not surprising, since adding a finite value to an infinite value should result in an infinite value.
That said, most of the values of i
that satisfy i == i + 1
are simply large double
(or float
) values:
For example:
double i = Double.MAX_VALUE;
or
double i = 1000000000000000000.0;
or
float i = 1000000000000000000.0f;
The double
and float
types have limited precision, so if you take a large enough double
or float
value, adding 1
to it will result in the same value.
edited Nov 29 at 8:22
answered Nov 28 at 9:33
Eran
275k36443528
275k36443528
9
Or(double)(1L<<53)
-- orfloat i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
3
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
2
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
3
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
2
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
|
show 11 more comments
9
Or(double)(1L<<53)
-- orfloat i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
3
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
2
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
3
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
2
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
9
9
Or
(double)(1L<<53)
-- or float i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
Or
(double)(1L<<53)
-- or float i = (float)(1<<24)
– dave_thompson_085
Nov 28 at 9:43
3
3
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
@Ruslan: Any mathematician would disagree. Floating point numbers make very little sense. They are non-associative, non-reflexive (NaN != NaN), and not even substitutable (-0 == 0, but 1/0 != 1/-0). So most of the machinery of algebra is inapplicable.
– Kevin
Nov 28 at 16:35
2
2
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
@Kevin while floating-point numbers can't indeed make too much sense in general, the behavior of infinities (which is what is described in that sentence) was designed to make sense.
– Ruslan
Nov 28 at 16:38
3
3
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
@Kevin To be fair to floats, if you deal with infinities or undefined values you can't assume the properties you listed in algebra either.
– Voo
Nov 28 at 17:11
2
2
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
@Kevin: IMHO, floating-point maths could have made a lot more sense if they'd replaced the concepts of "positive and negative zero" sign positive, negative, and unsigned "infinitesimals" along with one "true zero", and made NaN equal to itself. True zero could behave as an additive identity in all cases, and something operations involving division by infinitesimals would lose their bias towards assuming the infinitesimals are positive.
– supercat
Nov 28 at 17:15
|
show 11 more comments
up vote
57
down vote
These puzzles are described in detail in the "Java Puzzlers: Traps, Pitfalls, and Corner Cases" book by Joshua Bloch and Neal Gafter.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
or:
double i = 1.0e40;
while (i == i + 1) {}
both will result in an infinite loop, because adding 1
to a floating-point value that is sufficiently large will not change the value, because it doesn't "bridge the gap" to its successor1.
A note about the second puzzle (for future readers):
double i = Double.NaN;
while (i != i) {}
also results in an infinite loop, because NaN is not equal to any floating-point value, including itself 2.
1 - Java Puzzlers: Traps, Pitfalls, and Corner Cases (chapter 4 - Loopy Puzzlers).
2 - JLS §15.21.1
7
There should be a seperate hell for everyone that usesi
as a non integer variable. Or a as a counter at all... Not your fault I know...
– Kami Kaze
Nov 29 at 8:56
@KamiKaze Especially since several high-level languages havei
defined assqrt(-1)
by default and you end up overloading -- actually overriding -- this value.
– Carl Witthoft
Nov 29 at 16:10
add a comment |
up vote
57
down vote
These puzzles are described in detail in the "Java Puzzlers: Traps, Pitfalls, and Corner Cases" book by Joshua Bloch and Neal Gafter.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
or:
double i = 1.0e40;
while (i == i + 1) {}
both will result in an infinite loop, because adding 1
to a floating-point value that is sufficiently large will not change the value, because it doesn't "bridge the gap" to its successor1.
A note about the second puzzle (for future readers):
double i = Double.NaN;
while (i != i) {}
also results in an infinite loop, because NaN is not equal to any floating-point value, including itself 2.
1 - Java Puzzlers: Traps, Pitfalls, and Corner Cases (chapter 4 - Loopy Puzzlers).
2 - JLS §15.21.1
7
There should be a seperate hell for everyone that usesi
as a non integer variable. Or a as a counter at all... Not your fault I know...
– Kami Kaze
Nov 29 at 8:56
@KamiKaze Especially since several high-level languages havei
defined assqrt(-1)
by default and you end up overloading -- actually overriding -- this value.
– Carl Witthoft
Nov 29 at 16:10
add a comment |
up vote
57
down vote
up vote
57
down vote
These puzzles are described in detail in the "Java Puzzlers: Traps, Pitfalls, and Corner Cases" book by Joshua Bloch and Neal Gafter.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
or:
double i = 1.0e40;
while (i == i + 1) {}
both will result in an infinite loop, because adding 1
to a floating-point value that is sufficiently large will not change the value, because it doesn't "bridge the gap" to its successor1.
A note about the second puzzle (for future readers):
double i = Double.NaN;
while (i != i) {}
also results in an infinite loop, because NaN is not equal to any floating-point value, including itself 2.
1 - Java Puzzlers: Traps, Pitfalls, and Corner Cases (chapter 4 - Loopy Puzzlers).
2 - JLS §15.21.1
These puzzles are described in detail in the "Java Puzzlers: Traps, Pitfalls, and Corner Cases" book by Joshua Bloch and Neal Gafter.
double i = Double.POSITIVE_INFINITY;
while (i == i + 1) {}
or:
double i = 1.0e40;
while (i == i + 1) {}
both will result in an infinite loop, because adding 1
to a floating-point value that is sufficiently large will not change the value, because it doesn't "bridge the gap" to its successor1.
A note about the second puzzle (for future readers):
double i = Double.NaN;
while (i != i) {}
also results in an infinite loop, because NaN is not equal to any floating-point value, including itself 2.
1 - Java Puzzlers: Traps, Pitfalls, and Corner Cases (chapter 4 - Loopy Puzzlers).
2 - JLS §15.21.1
edited Nov 28 at 10:38
answered Nov 28 at 10:01
Oleksandr
8,56043768
8,56043768
7
There should be a seperate hell for everyone that usesi
as a non integer variable. Or a as a counter at all... Not your fault I know...
– Kami Kaze
Nov 29 at 8:56
@KamiKaze Especially since several high-level languages havei
defined assqrt(-1)
by default and you end up overloading -- actually overriding -- this value.
– Carl Witthoft
Nov 29 at 16:10
add a comment |
7
There should be a seperate hell for everyone that usesi
as a non integer variable. Or a as a counter at all... Not your fault I know...
– Kami Kaze
Nov 29 at 8:56
@KamiKaze Especially since several high-level languages havei
defined assqrt(-1)
by default and you end up overloading -- actually overriding -- this value.
– Carl Witthoft
Nov 29 at 16:10
7
7
There should be a seperate hell for everyone that uses
i
as a non integer variable. Or a as a counter at all... Not your fault I know...– Kami Kaze
Nov 29 at 8:56
There should be a seperate hell for everyone that uses
i
as a non integer variable. Or a as a counter at all... Not your fault I know...– Kami Kaze
Nov 29 at 8:56
@KamiKaze Especially since several high-level languages have
i
defined as sqrt(-1)
by default and you end up overloading -- actually overriding -- this value.– Carl Witthoft
Nov 29 at 16:10
@KamiKaze Especially since several high-level languages have
i
defined as sqrt(-1)
by default and you end up overloading -- actually overriding -- this value.– Carl Witthoft
Nov 29 at 16:10
add a comment |
up vote
1
down vote
Just an idea: what about booleans?
bool i = TRUE;
Isn't this a case where i + 1 == i
?
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
5
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no+
operator that takes aboolean
and anint
as operands).
– Eran
Nov 30 at 9:05
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
add a comment |
up vote
1
down vote
Just an idea: what about booleans?
bool i = TRUE;
Isn't this a case where i + 1 == i
?
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
5
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no+
operator that takes aboolean
and anint
as operands).
– Eran
Nov 30 at 9:05
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
add a comment |
up vote
1
down vote
up vote
1
down vote
Just an idea: what about booleans?
bool i = TRUE;
Isn't this a case where i + 1 == i
?
Just an idea: what about booleans?
bool i = TRUE;
Isn't this a case where i + 1 == i
?
answered Nov 29 at 15:09
Dominique
1,46541538
1,46541538
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
5
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no+
operator that takes aboolean
and anint
as operands).
– Eran
Nov 30 at 9:05
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
add a comment |
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
5
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no+
operator that takes aboolean
and anint
as operands).
– Eran
Nov 30 at 9:05
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
depends on the language. Many languages automatically coerce booleans to ints when combined with an int. Others do as you suggest - coercing the int to a boolean.
– Carl Witthoft
Nov 29 at 16:12
5
5
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no
+
operator that takes a boolean
and an int
as operands).– Eran
Nov 30 at 9:05
This question is a Java question, and your suggestion doesn't pass compilation in Java (which has no
+
operator that takes a boolean
and an int
as operands).– Eran
Nov 30 at 9:05
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
@Eran: that's the whole idea of operator overloading. You can make Java booleans behave like C++ ones.
– Dominique
Nov 30 at 9:26
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
Except that Java doesn't support operator overloading, so you can't.
– CupawnTae
yesterday
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53516189%2ffor-what-value-of-i-does-while-i-i-1-loop-forever%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
Any possibilities to override
.equals()
method? Since i is undeclared, we may use any class of what we want.– Geno Chen
Nov 28 at 9:35
7
@Raedwald studying "unprofessional" code makes you more "professional", so... Anyway, it's a good question
– Andrew Tobilko
Nov 28 at 9:56
11
Fun fact, in C# this also works for nullable numeric types whose values are
null
, sincenull == null
is true, andnull + 1
isnull
.– Eric Lippert
Nov 28 at 15:38
3
@EricDuminil: The situation is far worse than you imagine. In many languages, floating point arithmetic must be done in at least the 64 bits of precision specified by a double, which means that it can be done in higher precision at the whim of the compiler, and in practice this happens. I can point you at a dozen questions on this site from C# programmers who are wondering why
0.2 + 0.1 == 0.3
changes its value depending on compiler settings, the phase of the moon, and so on.– Eric Lippert
Nov 28 at 23:38
5
@EricDuminil: The blame for this mess falls on Intel, who gave us a chip set that does higher-precision and faster floating point arithmetic if the numbers can be enregistered, which means that the results of a floating point computation can change their values depending on how well the register scheduler in the optimizer works today. Your choices as a language designer are then between repeatable computations and fast, precise computations, and the community that cares about floating point math will opt for the latter.
– Eric Lippert
Nov 28 at 23:41