Je me demande si cette question peut être résolue en Java (je suis nouveau dans le langage). Voici le code:
class Condition {
// you can change in the main
public static void main(String[] args) {
int x = 0;
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
}
}
J'ai reçu la question suivante dans mon laboratoire: comment pouvez-vous ignorer le premier cas (c'est-à-dire faire le x == x
condition false) sans modifier la condition elle-même?
Une façon simple consiste à utiliser Float.NaN
:
float x = Float.NaN; // <--
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
Pas d'accord
Vous pouvez faire de même avec Double.NaN
.
De JLS §15.21.1. Opérateurs d'égalité numérique ==
et !=
:
Les tests d'égalité en virgule flottante sont effectués conformément aux règles de la norme IEEE 754:
Si l'un des opérandes est NaN, le résultat de
==
estfalse
mais le résultat de!=
esttrue
.En effet, le test
x!=x
esttrue
si et seulement si la valeur dex
est NaN....
int x = 0;
if (x == x) {
System.out.println("Not ok");
} else {
System.out.println("Ok");
}
Par le Spécifications du langage JavaNaN
n'est pas égal à NaN
.
Par conséquent, toute ligne qui a fait que x
soit égal à NaN
entraînerait cela, comme
double x=Math.sqrt(-1);
À partir du Java Spécifications du langage:
Les opérateurs en virgule flottante ne produisent aucune exception (§11). Une opération qui déborde produit un infini signé, une opération qui déborde produit une valeur dénormalisée ou un zéro signé, et une opération qui n'a pas de résultat mathématiquement défini produit NaN. Toutes les opérations numériques avec NaN comme opérande produisent en conséquence NaN. Comme cela a déjà été décrit, NaN n'est pas ordonné, donc une opération de comparaison numérique impliquant un ou deux NaN renvoie faux et toute comparaison! = Impliquant NaN renvoie vrai, y compris x! = x lorsque x est NaN.
Je ne sais pas si c'est une option, mais changer x
de variable locale en champ permettrait à un autre thread de changer sa valeur entre la lecture à gauche et à droite dans l'instruction if
.
Voici une courte démo:
class Test {
static int x = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Change());
t.setDaemon(true);
t.start();
while (true) {
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
break;
}
}
}
}
class Change implements Runnable {
public void run() {
while (true)
Test.x++;
}
}
Production:
⋮
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Not ok
La ligne remplacée pouvait lire.
double x = Double.NaN;
Cela entraînerait l'impression du gotcha.
La spécification du langage Java (JLS) dit:
Les opérateurs en virgule flottante ne produisent aucune exception (§11). Une opération qui déborde produit un infini signé, une opération qui déborde produit une valeur dénormalisée ou un zéro signé, et une opération qui n'a pas de résultat mathématiquement défini produit NaN. Toutes les opérations numériques avec NaN comme opérande produisent en conséquence NaN. Comme cela a déjà été décrit, NaN n'est pas ordonné, donc une opération de comparaison numérique impliquant un ou deux NaN renvoie faux et toute comparaison! = Impliquant NaN renvoie vrai, y compris x! = X lorsque x est NaN.
J'ai réussi à obtenir un Gotcha!
à partir de ceci:
volatile Object a = new Object();
class Flipper implements Runnable {
Object b = new Object();
public void run() {
while (true) {
Object olda = a;
a = b;
a = olda;
}
}
}
public void test() {
new Thread(new Flipper()).start();
boolean gotcha = false;
while (!gotcha) {
// I've added everything above this - I would therefore say still legal.
if (a == a) {
System.out.println("Not yet...");
} else {
System.out.println("Gotcha!");
// Uncomment this line when testing or you'll never terminate.
//gotcha = true;
}
}
}
Il y a tellement de solutions:
class A extends PrintStream {
public A(PrintStream x) {super(x);}
public void println(String x) {super.println("Not ok");}
public static void main(String[] args) {
System.setOut(new A(System.out));
int x = 0;
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
}
}
Une solution simple est:
System.out.println("Gotcha!");if(false)
if( a == a ){
System.out.println("Not yet...");
} else {
System.out.println("Gotcha!");
}
Mais je ne connais pas toutes les règles de cette énigme ...
:) Je sais que c'est une triche, mais sans connaître toutes les règles, est-ce la solution la plus simple à la question :)
Créez votre propre classe System
dans le même paquet avec Condition
.
Dans ce cas, votre classe System
masquera Java.lang.System
classe
class Condition
{
static class System
{
static class out
{
static void println(String ignored)
{
Java.lang.System.out.println("Not ok");
}
}
}
public static void main (String[] args) throws Java.lang.Exception
{
int x = 0;
if (x == x)
{
System.out.println("Not ok");
}
else
{
System.out.println("Ok");
}
}
}
En utilisant la même approche de sortie de saut/changement d'une autre réponse:
class Condition {
public static void main(String[] args) {
try {
int x = 1 / 0;
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
} catch (Exception e) {
System.out.println("Not ok");
}
}
}