Come può "while (i == i);" essere un ciclo non infinito in una singola applicazione thread?


141

Ho appena ricevuto una domanda a cui non posso rispondere.

Supponiamo di avere questa definizione di loop in Java:

while (i == i) ;

Qual è il tipo ie il valore di ise il loop non è un loop infinito e il programma utilizza solo un thread ?


7
oh, per l'amor di Dio, la gente avrebbe l'onore di commentare il motivo per cui ha votato? questo è etichettato come un indovinello, qual è il problema ???
user54579,

10
Penso che alcune persone non possano smettere di votare per nulla.
FerranB,

1
Bah, scusa per aver causato questo: / Volevo davvero solo la risposta, e non sono riuscito a risolverlo da solo.
Zizzencs,

1
@nickolai, questa è la natura di SO - il downvoting drive-by è purtroppo una realtà e l'idea di richiedere un commento è stata discussa e respinta. Ma sembra che la "comunità" sia a favore di questa domanda dopo tutto.
paxdiablo,

1
Uno dei trucchi di questo tipo di domanda è che le persone assumono il tipo di determinati nomi di variabili, cioè i è un int, d è un doppio, s è una stringa o un corto, ch è un carattere, l è un lungo, b per byte o booleano. Devi chiederti che tipo è suggerito e quale potrebbe essere.
Peter Lawrey,

Risposte:


125
double i = Double.NaN;

L'API per Double.equals () specifica la risposta: "Double.NaN == Double.NaN ha il valore falso". Questo è elaborato nella specifica del linguaggio Java in " Tipi, formati e valori in virgola mobile ":

NaNè ordinata, in modo che il numerico operatori di confronto <, <=, >, e >= ritorno falsese uno o entrambi gli operandi sono NaN. L'operatore di uguaglianza ==ritorna falsese uno degli operandi lo è NaNe l'operatore di disuguaglianza !=ritorna truese uno degli operandi lo è NaN. In particolare, x!=xè truese e solo se xèNaN , e (x<y) == !(x>=y)sarà falsese xo yè NaN.


1
OH, quindi PUOI fare "Not a Number"!
Filip Ekberg,

12
è matematicamente solido, perché un numero irreale dovrebbe essere uguale a un altro? 5/0! = Sqrt (-4)
Gordon Gustafson,

2
@CrazyJugglerDrummer: Forse, ma allo stesso modo x == xdovrebbe essere sempre vero. Perché qualcosa non dovrebbe eguagliarsi?
Bart van Heukelom,

1
Bart: perché davvero, l'ignoto non è sempre uguale all'ignoto. A volte è utile, ecco perché i database hanno NULL ...
Konerak,

2
@inovaovao: no, in un DB, null=nullè nullo. NULL IS NULLè 1.
Konerak,

29

Il valore di iè quindi Non valido. "Non un numero".

Dopo aver cercato su Google, ho scoperto che PUOI avere NaN (Not a Number) in Java! Pertanto, un numero di virgola mobile è il tipo di dati e il valore è NaN. Vedi qui


12
Sì, tutto qui. Il valore di i è Jon Skeet.
Andrew Rollings,

In genere odio le persone che hanno votato per nessun motivo ... Sono stato il primo a dire "Not a Number" ma non pensavo che Java potesse gestirlo, dal momento che non gestisce niente di interessante.
Filip Ekberg,


9
float i = Float.NaN;
while(i == i) ;
System.out.println("Not infinite!");

8

Non sono sicuro, ma credo che (i == i) non sia un'operazione atomica in un processo multithread, quindi se il valore i verrà modificato da un altro thread tra i push del suo valore da impilare sul thread che esegue il ciclo, tale condizione può sii falso.


8

Dato che altri hanno detto che è NaN, mi sono incuriosito dall'implementazione ufficiale (JDK 6) di Double.isNaN, ed ecco:

/**
 * 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

Pensa a Nan come l'equivalente di un'eccezione ma usa un valore magico all'interno di un calcolo. Perché un calcolo fallito - ad es. Radice quadrata di un negativo, divisione per zero ecc. - non ha senso confrontarli con qualsiasi altra cosa. Dopotutto se dividere per zero è un nan è equivalente alla radice quadrata di -2 o alla radice quadrata di -3?

Nan consente un calcolo che include un passaggio che restituisce una risposta non valida da completare senza introdurre eccezioni aggiuntive. Per verificare che la risposta sia un valore, è sufficiente provare la non nandness (è questa la parola se non la metto) tramite Float.isNan () o equivalente.


3
Sarebbe più facile pensarlo come un eccezionalità, ma se davvero sapessi cosa fosse un eccezionalità :-).
paxdiablo,

2

Vorrei aggiungere

float i = Float.NaN;

così come

double i = Double.NaN;

Un trucco comune in questo tipo di domande presuppone che io sia un int. Altre ipotesi comuni potrebbero essere s è una stringa, x, y sono un doppio, ch è un carattere, b è un byte ecc. Se vedi una domanda come questa puoi scommettere che 'i' non è il suo tipo previsto.

Una domanda simile è; Questo non gira mai, cos'è "x"

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

Un'altra domanda che mi piace è; Questo ciclo è un ciclo infinito, quali sono i possibili valori di x. (: Ne conto dodici) :)

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

0

So che questa è una domanda Java, ma considerare la domanda per altre lingue è intrigante.

In C, un tipo semplice come 'int' potrebbe esibire 'terminare prima che l'universo si raffreddi' comportamento se 'i' fosse dichiarato volatile (quindi il compilatore sarebbe costretto a fare due letture di 'i' per ogni iterazione) e se "i" fosse effettivamente in memoria dove qualcos'altro potrebbe influenzarlo. Quindi il ciclo terminerebbe quando 'i' cambiava tra le due letture di una singola iterazione. ( Aggiunto : un posto possibile - in un microcomputer in cui "i" si trova effettivamente all'indirizzo di una porta I / O, forse collegato a un sensore di posizione. Sarebbe più plausibile se "i" fosse una variabile puntatore ( un puntatore alla memoria volatile) e l'affermazione era ' while (*i == *i);'.)

Come evidenziato da altre risposte, in C ++, l'operatore '==' può essere fornito dall'utente se io sono di una classe definita dall'utente, quindi tutto potrebbe essere possibile.

Piuttosto come NaN, in un linguaggio basato su SQL, il ciclo non sarebbe infinito se il valore di i fosse NULL; tuttavia, qualsiasi valore non NULL renderebbe il ciclo infinito. Questo è piuttosto come Java, dove qualsiasi numero (al contrario di NaN) rende il ciclo infinito.

Non vedo il costrutto avere alcun uso pratico, ma è una domanda a quiz interessante.


0

Sono stato sorpreso di non vedere questa soluzione:

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

In risposta a un commento, prova a eseguire questo:

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

x dovrebbe sempre essere uguale all'arcoseno (sin (x)) in teoria, ma in pratica non lo è.


3
Perchè no? Stai facendo esattamente lo stesso calcolo su esattamente gli stessi dati, entrambi i risultati conterranno esattamente lo stesso errore.
Loren Pechtel,

Non riesco a ricordare esattamente dove l'ho letto, ma a seconda della tua macchina / implementazione, il sin (x) su una chiamata di funzione ha una minuscola possibilità di eguagliare sin (x) di una chiamata diversa. Ha a che fare con l'accuratezza delle cifre in virgola mobile (qualcosa di speciale nelle funzioni di trigger che le rende non restituire lo stesso valore due volte).
jkeys,

Vedi il mio aggiornamento Arcsine "annulla" il peccato di x, quindi dovrebbero essere uguali, ma non lo sono.
jkeys,

Non è la stessa cosa. Come ha detto Loren, stai eseguendo la stessa identica operazione x, che dovrebbe produrre lo stesso risultato esatto con la stessa esattezza. Arcsin non può invertire il risultato di un peccato con numeri in virgola mobile perché il valore passato a asin()non sarà esattamente preciso. Pertanto, il risultato di asin()sarà impreciso, rendendo x == asin(sin(x))falso. Inoltre, arcsin non necessariamente "annulla" un'operazione sin: la funzione sin può dare lo stesso risultato per più valori di x, motivo per cui asin()restituisce solo numeri compresi tra -π / 2 e π / 2.
hbw

2
In altre parole, arcsin non può sempre "annullare" la funzione sin perché è impossibile per arcsin sapere qual era l'angolo originale. Ad esempio, il peccato di π / 2 e 5π / 2 dà 1. Ma cos'è l'arcosina (1)? Ovviamente non può restituirli entrambi, giusto? Pertanto, il risultato di arcsin deve essere limitato a un intervallo di radianti 2π, il che significa che non può effettivamente annullare il risultato della funzione sin se l'angolo originale non è compreso tra 0 e 2π, o nel caso di C, -π / 2 e π / 2. (In effetti, arcsin (sin (5π / 2)) = π / 2). Comunque, questa è stata una spiegazione molto lunga, ma spero che aiuti a chiarire eventuali equivoci.
hbw

0

Ciclo non infinito, un 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);
    }
}

-1

i == inon è atomico. Provato da tale programma:

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

Aggiorna Ecco un altro esempio di ciclo non infinito (non vengono creati nuovi thread).

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 Quello che dici al fatto che non c'è possibilità di scrivere un programma Java usando un thread :), quindi tutte le altre soluzioni usano almeno due thread (esattamente lo stesso del mio secondo programma nella sezione 'Aggiornamento').
Andrey,

Non sta frenando il ciclo. Qualsiasi codice dopo while (i == i);non verrà mai eseguito.
aalku,

Finalize utilizza un altro thread, ma è una buona cosa sottolineare. È il motivo per cui la domanda originale diceva "e il programma usa solo un thread" .. in un certo senso affermando esplicitamente che questa è la risposta ovvia e desiderano che tu guardi oltre.
Bill K,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.