“(i == i);”하는 방법 단일 스레드 응용 프로그램에서 무한 루프가 아닌가?


141

방금 대답 할 수없는 질문이 있습니다.

Java에이 루프 정의가 있다고 가정하십시오.

while (i == i) ;

루프가 무한 루프가 아니고 프로그램이 하나의 스레드 만 사용 하는 경우 의 유형 i과 값은 무엇입니까?i


7
오, 신을 위해서 사람들은 왜 그들이 투표에 실패했는지에 대해 언급하는 영광을 가질까요? 이것은 수수께끼로 태그되어 있습니다. 무엇이 문제입니까 ???
user54579

10
나는 어떤 사람들은 아무것도 거절하지 않을 수 있다고 생각합니다.
FerranB

1
Bah,이 문제를 일으켜서 죄송합니다 : / 나는 정말로 답을 원했고 스스로 해결할 수 없었습니다.
Zizzencs

1
@nickolai, 그것은 SO의 본질입니다-드라이브 바이 다운 보팅은 불행히도 현실이며 의견을 요구하는 아이디어는 논의되고 거부되었습니다. 그러나 "커뮤니티"가 결국이 질문에 찬성하는 것처럼 보입니다.
paxdiablo

1
이런 종류의 질문의 요점 중 하나는 사람들이 특정 변수 이름의 유형을 가정한다는 것입니다. 즉, i는 int, d는 double, s는 문자열 또는 short, ch는 char, l은 long, b입니다. 바이트 또는 부울. 어떤 유형이 제안되고 어떤 유형인지 제안해야합니다.
Peter Lawrey

답변:


125
double i = Double.NaN;

Double.equals () 용 API는 "Double.NaN == Double.NaN의 값은 false"입니다. 이것은 " 부동 소수점 유형, 형식 및 값 " 의 Java 언어 사양에 자세히 설명되어 있습니다 .

NaN수치 비교 연산자, 그래서 순서가있다 <, <=, >, 및 >= 반환 false하나 또는 두 피연산자가있는 경우 NaN. 항등 연산자의 ==반환 false피연산자 인 경우 NaN, 그리고 비항 등 연산자의 !=반환 true피연산자 인 경우 NaN. 특히, x!=xtrue경우에만 xISNaN 하고 (x<y) == !(x>=y)있을 것입니다 false경우 x또는 y이다 NaN.


1
OH 그래서 당신은 "숫자가 아님"을 할 수 있습니다!
Filip Ekberg

12
수학적으로 견고합니다. 왜 하나의 비현실적인 숫자가 다른 숫자와 같아야합니까? 5/0! = sqrt (-4)
Gordon Gustafson 2018 년

2
@CrazyJugglerDrummer : 어쩌면 x == x항상 마찬가지입니다. 왜 아무것도 같지 않아야합니까?
바트 반 Heukelom

1
바트 : 알 수없는 것이 항상 알 수없는 것은 아닙니다. 때로는 유용합니다. 데이터베이스에 NULL이있는 이유입니다.
Konerak

2
@inovaovao : DB에서 no null=null는 null입니다. NULL IS NULL
Konerak

29

그러면 값이 i유효하지 않습니다. "숫자가 아님".

인터넷 검색 후 Java에서 NaN (Not a Number)을 가질 수 있음을 알았습니다! 따라서 Float Pointing 숫자는 데이터 유형이고 값은 NaN입니다. 여기를 참조 하십시오


12
그렇습니다. i의 가치는 Jon Skeet입니다.
Andrew Rollings

나는 일반적으로 아무 이유없이 downvote 사람들을 싫어 ... 나는 "숫자가 아님"이라고 말했지만 자바가 그것을 처리 할 수 ​​있다고 생각하지 않았습니다. 다른 멋진 것을 처리하지 않기 때문입니다.
Filip Ekberg

12
double i = Double.NaN;

NaN은 자체를 포함하여 어떤 것과도 같지 않습니다.



8

확실하지 않지만 (i == i) 멀티 스레드 프로세스에서 원자 연산이 아니라고 생각합니다. 따라서 루프를 실행하는 스레드에서 스택 값을 푸시하는 사이에 다른 스레드에 의해 i 값이 변경되면 해당 조건은 거짓이다.


8

다른 사람들이 NaN이라고 말했기 때문에 공식 (JDK 6) 구현에 대해 궁금해했습니다 Double.isNaN.

/**
 * 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);
}

2

Nan을 예외와 동등한 것으로 생각하지만 계산에서 마술 값을 사용합니다. 계산이 실패 했으므로 (예 : 음의 제곱근, 0으로 나누기 등) 다른 것과 비교하는 것은 의미가 없습니다. 결국 0으로 나누기가 nan이면 -2의 제곱근 또는 -3의 제곱근과 같습니다.

Nan은 추가 예외를 발생시키지 않고 유효하지 않은 답변을 반환하는 단계를 포함하는 계산을 허용합니다. 답이 가치인지 확인하려면 Float.isNan () o를 통해 nandness가 아닌지 테스트하십시오.


3
exceptiolbut가 무엇인지 실제로 알았다면 exceptiolbut로 생각하는 것이 더 쉽습니다. :-).
paxdiablo

2

나는 추가 할 것이다

float i = Float.NaN;

만큼 잘

double i = Double.NaN;

이러한 종류의 질문에서 일반적인 트릭은 i가 int라고 가정한다는 것입니다. 다른 일반적인 가정은 s는 String, x, y는 double, ch는 char, b는 byte 등일 수 있습니다. 이와 같은 질문이 표시되면 'i'가 예상 유형이 아니라고 확신 할 수 있습니다.

비슷한 질문이다; 이것은 반복되지 않습니다. 'x'는 무엇입니까?

while(x == x && x != x + 0) { }

내가 좋아하는 또 다른 질문은; 이 루프는 무한 루프이며 x의 가능한 값은 무엇입니까? (: 나는 그들 중 12 명을 센다 :)

while(x != 0 && x == -x) { }

0

나는 이것이 Java 질문이라는 것을 알고 있지만 다른 언어에 대한 질문을 고려하는 것은 흥미 롭습니다.

C에서 'int'와 같은 간단한 유형은 'i'가 소멸성으로 선언 된 경우 '유니버스가 차가워지기 전에 종료'동작을 나타낼 수 있습니다 (따라서 컴파일러는 각 반복에 대해 'i'를 두 번 읽습니다) 그리고 'i'가 실제로 다른 것에 영향을 줄 수있는 메모리에 있다면. 그런 다음 단일 반복의 두 번의 읽기 사이에서 'i'가 변경되면 루프가 종료됩니다. ( 추가 : 가능한 위치- 'i'가 실제로 I / O 포트의 주소에 위치하고 위치 센서에 연결된 마이크로 컴퓨터에서 'i'가 포인터 변수 인 경우 더 적합합니다 ( 휘발성 메모리에 대한 포인터) 및 명령문은 ' while (*i == *i);'입니다.)

다른 답변에서 알 수 있듯이 C ++에서 사용자 정의 클래스에 있으면 사용자가 '=='연산자를 제공 할 수 있으므로 모든 것이 가능할 수 있습니다.

NaN과 달리 SQL 기반 언어에서 i 값이 NULL이면 루프가 무한하지 않습니다. 그러나 NULL이 아닌 값은 루프를 무한대로 만듭니다. 이것은 NaN과 달리 숫자가 루프를 무한대로 만드는 Java와 비슷합니다.

나는 구조가 실제로 사용되는 것을 보지 못하지만 흥미로운 사소한 질문입니다.


0

이 솔루션을 보지 못한 것에 놀랐습니다.

while (sin(x) == sin(x)) //probably won't eval to true

주석에 대한 응답으로 다음을 실행하십시오.

double x = 10.5f;
assert (x == asin(sin(x)));

x는 이론상으로 항상 arcsine (sin (x))과 같아야하지만 실제로는 그렇지 않습니다.


3
왜 안돼? 정확히 동일한 데이터에 대해 정확히 동일한 계산을 수행하면 두 결과에 정확히 동일한 오류가 포함됩니다.
Loren Pechtel

정확히 읽은 위치를 기억할 수는 없지만 컴퓨터 / 구현에 따라 한 함수 호출의 sin (x)는 다른 호출의 sin (x)와 같을 가능성이 적습니다. 부동 소수점 자릿수의 정확도와 관련이 있습니다 (삼각 함수가 같은 값을 두 번 반환하지 않도록하는 함수는 특별한 것입니다).
jkeys

내 업데이트를 참조하십시오. 아크 사인은 x의 죄를 "취소"하므로 그것들은 같아야하지만 그렇지는 않습니다.
jkeys

그것은 같은 것이 아닙니다. Loren이 말한 것처럼에 대해 동일한 작업을 수행 x하면 정확히 동일한 정확도로 동일한 결과를 얻을 수 있습니다. 전달 된 값 asin()이 정확하게 정확하지 않기 때문에 Arcsin은 부동 소수점 숫자를 가진 sin의 결과를 되돌릴 수 없습니다 . 따라서 결과 asin()가 정확하지 않아 x == asin(sin(x))거짓이됩니다. 또한 arcsin은 반드시 sin 연산을 "실행 취소"할 필요는 없습니다. sin 함수는 x의 여러 값에 대해 동일한 결과를 제공 할 수 있으므로 asin()-π / 2와 π / 2 사이의 숫자 만 반환합니다.
hbw

2
다시 말해, arcsin이 sin 함수를 "실행 취소"할 수는 없습니다. arcsin이 원래 각도가 무엇인지 아는 것은 불가능하기 때문입니다. 예를 들어, π / 2와 5π / 2의 죄는 1입니다. 그러나 arcsin (1)은 무엇입니까? 분명히 둘 다 되돌릴 수는 없습니다. 따라서 arcsin의 결과는 2π 라디안 범위로 제한되어야합니다. 즉, 원래 각도가 0에서 2π 사이에 있지 않거나 C의 경우 -π / 2 및 π / 2. (실제로 arcsin (sin (5π / 2)) = π / 2.) 어쨌든, 그것은 정말 긴 설명 이었지만 오해를 없애는 데 도움이되기를 바랍니다.
hbw

0

무한 루프가 아닌 하나의 스레드 :)

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

-1

i == i원자가 아닙니다. 그러한 프로그램에 의해 입증 :

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

업데이트 다음은 무한 루프가 아닌 예입니다 (새 스레드가 생성되지 않음).

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

@Charles Goodwin 하나의 스레드를 사용하여 Java 프로그램을 작성할 가능성이 없다는 사실에 대해 말하면서 다른 모든 솔루션은 적어도 두 개의 스레드를 사용합니다 ( '업데이트'섹션의 두 번째 프로그램과 동일).
Andrey

루프를 제동하지 않습니다. 모든 코드는 while (i == i);실행 되지 않습니다.
aalku

Finalize는 다른 스레드를 사용하지만 지적하는 것이 좋습니다. 원래 질문에 "프로그램은 하나의 스레드 만 사용합니다"라고 말한 이유입니다. 이것은 명백한 답변이며 더 자세히보기를 원한다고 명시합니다.
Bill K
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.