108

我想知道这个问题是否可以用 Java 解决(我是该语言的新手)。这是代码:

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");
        }
    }
}

我在实验室收到了以下问题:如何在x == x不修改条件本身的情况下跳过第一种情况(即使条件为假)?

4

10 回答 10

174

一种简单的方法是使用Float.NaN

float x = Float.NaN;  // <--

if (x == x) {
    System.out.println("Ok");
} else {
    System.out.println("Not ok");
}
不好

您可以对Double.NaN.


来自JLS §15.21.1。数值等式运算符==!=

浮点相等性测试根据 IEEE 754 标准的规则执行:

  • 如果任一操作数为 NaN,则 is 的结果是is==false结果。!=true

    实际上,测试x!=xtrue当且仅当 的值为xNaN 时。

...

于 2013-10-17T01:17:22.797 回答
159
int x = 0;
if (x == x) {
    System.out.println("Not ok");
} else {
    System.out.println("Ok");
}
于 2013-10-17T01:18:30.373 回答
147

Java 语言规范 NaN不等于NaN.

因此,任何导致x等于的行NaN都会导致这种情况,例如

double x=Math.sqrt(-1);

来自 Java 语言规范:

浮点运算符不会产生异常(§11)。上溢运算产生有符号无穷大,下溢运算产生非规格化值或有符号零,而没有数学确定结果的运算产生 NaN。所有以 NaN 作为操作数的数值运算都会产生 NaN 作为结果。如前所述,NaN 是无序的,因此涉及一个或两个 NaN 的数值比较操作返回 false,任何涉及 NaN 的 != 比较都返回 true,包括当 x 为 NaN 时的 x!=x。

于 2013-12-04T12:02:25.820 回答
73

不确定这是否是一个选项,但从局部变量更改为字段将允许其他线程在语句x中读取左侧和右侧之间更改其值。if

这是简短的演示:

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++;
    }
}

输出:

⋮
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Not ok
于 2013-10-17T01:45:39.663 回答
56

替换的行可以读取。

double x = Double.NaN;

这将导致打印问题。

Java 语言规范 (JLS) 说:

浮点运算符不会产生异常(§11)。上溢运算产生有符号无穷大,下溢运算产生非规格化值或有符号零,而没有数学确定结果的运算产生 NaN。所有以 NaN 作为操作数的数值运算都会产生 NaN 作为结果。如前所述,NaN 是无序的,因此涉及一个或两个 NaN 的数值比较操作返回 false,任何涉及 NaN 的 != 比较都返回 true,包括当 x 为 NaN 时的 x!=x。

于 2013-12-04T12:06:50.777 回答
30

我设法从中得到了一个Gotcha!

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;
    }
  }
}
于 2013-12-04T12:21:44.877 回答
26

有很多解决方案:

import java.io.PrintStream;

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");
        }
    }
}
于 2013-10-17T18:35:31.957 回答
25

一种简单的解决方案是:

System.out.println("Gotcha!");if(false)
if( a == a ){
  System.out.println("Not yet...");
} else {
  System.out.println("Gotcha!");
}

但我不知道这个谜语的所有规则......

:) 我知道这是作弊,但在不了解所有规则的情况下,这是解决问题的最简单方法吗 :)

于 2013-12-04T12:09:26.847 回答
11

System在同一个包中创建您自己的类Condition
在这种情况下,您的System班级将隐藏java.lang.System班级

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");
        }
    }
}  

Ideone 演示

于 2013-11-04T19:52:05.387 回答
9

从另一个答案使用相同的跳过/更改输出方法:

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");
        }
    }
}
于 2013-10-22T22:22:20.380 回答