Ciclo for impazzito

di il
18 risposte

Ciclo for impazzito

Ecco un bel problema:

double x;
for(x=-10.00;x<=10.00;x+=0.01)
  cout<<x;
Teoricamente x dovrebbe assumere tutti i valori con due decimali da -10 a 10, ma arrivata allo 0 non vale 0, bensì -1.68889e-013. perché?

18 Risposte

  • Re: Ciclo for impazzito

    L'imprecisione è una caratteristica dei double
    Ti suggerisco di impostare il for con un intero, con i valori moltiplicati per 100: quindi vai da -1000 a +1000 e incrementi di 1; all'interno del ciclo ottieni il valore double dividendo per 100.
  • Re: Ciclo for impazzito

    perché?
    Il perché lo trovi nella teoria di informatica di base, anzi, della teoria dei sistemi di numerazione e di rappresentazione in binario dei valori in virgola mobile.

    Sarebbe troppo lungo e poco utile, ti suggerisco di seguire il consiglio che hai avuto.
  • Re: Ciclo for impazzito

    Continua a non funzionare
  • Re: Ciclo for impazzito

    Eppure è proprio lo 0 che mi serve!!
  • Re: Ciclo for impazzito

    Anche se e' proprio lo zero che ti serve, non ci puoi fare nulla, non lo puoi avere

    Quello che puoi fare, eventualmente, e' quello di dire: e' zero ma con un errore di epsilon.

    Quindi invece di fare il controllo: x == 0, devi fare un controllo del tipo: abs(x) <= epsilon

    E se metti epsilon = 0, hai esattamente il tuo test originale.

    Oppure segui il consiglio di @candaluar, altrettanto valido!
  • Re: Ciclo for impazzito

    ANDPRI ha scritto:


    Continua a non funzionare
    Cosa? Il codice di candaluar? O il tuo?

    Se insisti sul tuo allora non hai letto quello che ti ho scritto.
  • Re: Ciclo for impazzito

    Seguendo il suggerimento di migliorabile, potresti usare un if come questo per vedere se il valore è approssimativamente "zero":
    if(std::fabs(x) <= std::numeric_limits<float>::epsilon())
    //approssima con zero
    
    La chiamata std::numeric_limits<float>::epsilon() in questo caso rappresenta l'epsilon macchina visto come la differenza tra 1 e il minimo valore maggiore di 1 che è rappresentabile.
    Dai uno sguardo anche qua : http://www.cplusplus.com/reference/limits/numeric_limits/

    Per il tuo caso in particolare la soluzione dovrebbe andare, non sono sicuro che la cosa continui a funzionare se lo step diventa molto più piccolo di 0.01 e/o il range diventa più grande di [-10,10].
  • Re: Ciclo for impazzito

    Potrebbe anche scrivere
    
    double x;
    for(x=-1000; x<=1000; x+=1)
      cout << x/100.0;
    
  • Re: Ciclo for impazzito

    oregon ha scritto:


    Potrebbe anche scrivere
    
    double x;
    for(x=-1000; x<=1000; x+=1)
      cout << x/100.0;
    
    Si era quello che suggeriva candaluar, penso siano entrambe soluzioni valide.
  • Re: Ciclo for impazzito

    Veramente io intendevo
    double x;
    int ix;
    
    for(ix=-1000; ix<=1000; ix+=1)
    {
      x = (double)ix / 100.0;
      cout << x;
    }
    In fondo, perchè scomodare la virgola mobile se sono sufficienti solo due decimali?
  • Re: Ciclo for impazzito

    C'è un po' di confusione ...

    @candaluar ... proponeva il ciclo con gli interi e io avevo concordato ma ANDPRI (che non si è fatto più sentire) non sembrava d'accordo ...

    Allora avevo proposto una versione con i double, se questo poteva tranquillizzare ANDPRI ...

    Resta inteso che lavorare con gli interi per il ciclo è preferibile
  • Re: Ciclo for impazzito

    Si ma anche la soluzione di usare i decimali non funziona
  • Re: Ciclo for impazzito

    Intervengo unicamente per ricordare che anche le più blande norme di stile (come MISRA/C) proibiscono categoricamente l'uso di loop basati su variabili di induzione di tipo non intero, uniformente con i controlli statici e dinamici eseguiti dai vari ambienti di verifica del codice.

    Tale rigida proibizione dovrebbe considerarsi automaticamente estesa all'ambito scolastico, salvo casi assolutamente eccezionali di comprovata necessità didattica. Pertanto, per quanto riguarda l'OP, il costrutto che ha tentato di utilizzare non ha alcun senso e deve essere considerato unicamente un grossolano errore di progettazione. Se servono "esattamente due" decimali, e più in generale un numero prefissato a priori, l'optimum consiste nel lavorare in fixed point, un concetto elementare di straordinaria efficacia, che tuttavia stranamente pare mettere a dura prova perfino molti laureati in discipline connesse all'informatica.
  • Re: Ciclo for impazzito

    ANDPRI ha scritto:


    Si ma anche la soluzione di usare i decimali non funziona
    Quale?

    Come "non funziona"?

    Hai usato il ciclo con gli interi?


    SE scrivi qualche riga in più magari si perde meno tempo a chiederti ulteriori chiarimenti ...
Devi accedere o registrarti per scrivere nel forum
18 risposte