Presenza di valori negativi

Questo esercizio riguarda ancora l'uso dei cicli. Sia data una funzione f(x) a valori interi; si vuole sapere se esiste un valore intero x compreso in un certo intervallo dato in cui f(x) è negativa. Per esempio, dato f(x)=-x*x+90*i, ci si chiede se esiste un valore di x compreso fra 0 e 100 tale che f(x) sia negativa per quel valore.

Questo è un tipico esempio di utilizzo dei cicli. Infatti, il problema si può risolvere con un ciclo in cui una variabile assume tutti i valori interi compresi nell'intervallo. Per ogni valore, si valuta la funzione e si verifica se è positiva o negativa. Il programma SottoZero.java risolve il problema in questo modo.

/* 
  Verifica se esistono valori negativi per una funzione.
  Si valutano solo valori interi dell'argomento, e solo
  per un intervallo fissato.
*/

class SottoZero {
  public static void main(String[] args) {
    int x;
    int f;
    int positivo;

    positivo=1;

    for(x=0; x<=100; x=x+1) {
      f=-x*x+90*x;
      if( f<0 ) {
        positivo=0;
      }
    }

    if( positivo==1 ) {
      System.out.println("La funzione e' positiva nell'intervallo");
    }
    else {
      System.out.println("La funzione ha valori negativi");
    }
  }
}

Naturalmente, esistono altri programmi che fanno la stessa cosa. D'altra parte, molti programmi che sembrano risolvere questo problema sono in effetti errati. Per esempio, è facile pensare che la variabile positivo non sia necessaria, e procedere quindi secondo il programma seguente:

    for(i=0; i<=100; i=i+1) {		/* ERRATO */
      f=-i*i+90*i;
      if( f<0 ) {
        System.out.println("La funzione e' positiva nell'intervallo");
      }
      else {
        System.out.println("La funzione ha valori negativi");
      }
    }

In questo caso, per ogni valore di x viene stampato il messaggio che dice se la funzione è positiva oppure negativa. Si voleva invece una stampa sola, che riassumesse la presenza o meno di valori negativi nell'intervallo. Questo indica chiaramente che la stampa non si può fare all'interno del ciclo, perchè altrimenti si avrebbe un messaggio per ogni valore, e non uno solo alla fine. Per questa ragione è necessaria la variabile positivo, il cui valore alla fine indica la presenza di valori negativi, e permette quindi di decidere cosa stampare.

    for(i=0; i<=100; i=i+1) {		/* ERRATO */
      f=-i*i+90*i;
      if( f<0 ) {
        positivo=0;
      }
      else {
        positivo=1;
      }
    }

Questo è un altro errore tipico. A prima vista, il programma può sembrare corretto, dal momento che, per ogni valore di x si verifica se la funzione è positiva o negativa. Si supponga però che la funzione sia negativa in tutto l'intervallo tranne che per l'estremo superiore, ossia che f(x) sia negativa per x che va da 0 a 99, e sia positiva solo per x=100. Questo programma effettua la valutazione delle istruzioni interne al ciclo per ogni valore di x; l'ultima esecuzione avviene assegnando 100 ad x. A questo punto, si valuta f, che risulta positiva, per cui la condizione f<0 risulta falsa, e si assegna positivo=1;. La istruzione che segue il ciclo è la istruzione condizionale in cui la condizione è sul valore di positivo. A questo punto, viene stampato il messaggio che dice che la funzione è sempre positiva nell'intervallo. Questo comportamento è chiaramente errato, dal momento che, al contrario, la funzione è quasi sempre negativa nell'intervallo.

L'errore è che la variabile positivo cambia valore ad ogni esecuzione del ciclo. Questo è un errore, perchè in questo modo assume un valore che dipende solo dall'ultimo valore di x. Quello che invece si vuole fare è: si comincia assumendo che la funzione sia sempre positiva; se si trova un valore per cui è negativa si cambia il valore della variabile.