Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    Programmazione in C, funzione pow

    Ciao a tutti! Ho da poco iniziato a programmare in C per un esame, sto facendo un esercizio in cui devo definire una funzione per poi calcolare le X e le Y con un ciclo for nel main

    Il problema è che per le x comprese tra -2 e 0 mi da nan una volta che compilo.. cioè nella y in cui è presente pow(x,2./3.) e so che è questo il problema perché ho provato a toglierlo e non mi da più errore.. Se qualcuno può aiutarmi perché non ho idea di cosa non vada

    Questa è la funzione:

    double funz(double x){
    double y;
    if(x<-2 || x>=2)
    y=23./9.;
    else if(x>=-2 && x<=0)
    y=(3./7.*(cos(x)*sin(x)))-(2./3.*pow(x,(2./3.)));
    else
    y=(9./5.*log(x+1))-(sqrt(x*x+1));
    return y;
    }





  2. #2
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    155
    Qui avevo avuto lo stesso problema, mi pare, ed era stato risolto mettendo 2.0/3.0.
    Il problema mi sembra lo stesso, da una lettura veloce...sperando di esser stato utile

  3. #3
    @ing82: non c'entra, scrivere 2. o 2.0 è lo stesso (basta già il punto a specificare che si tratta di double).

    @martatos: il problema è che, anche se matematicamente x^(2/3) è ben definito anche sui negativi (in quanto definito come equivalente ad estrarre la radice cubica e poi fare il quadrato), operando in floating point non stai mai lavorando su frazioni esatte, ma sempre su loro approssimazioni finite (per dire, il 2./3. in questione in rappresentazione IEEE 754 di fatto è come se fosse la frazione 6004799503160661/9007199254740992). Per questo motivo, in generale elevare un numero negativo ad un numero floating point non ha nessun senso (visto che il fatto che venga fuori un numero immaginario o meno viene a dipendere dal fatto che per puro caso il risultato approssimato sia rappresentabile con una frazione con denominatore pari o dispari); di conseguenza, pow fallisce sempre se le si passa una base negativa e un esponente non intero.

    Per ovviare al tuo problema, puoi semplicemente fare pow(-x, 2./3.), riportandoti così al caso in cui x è positivo (e matematicamente x^(2/3) è uguale a (-x)^(2/3), visto che il 2 uccide il segno).
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Per completezza, aggiungo che prima di cimentarsi nell'uso di calcoli in C usando il FP IEEE 754 è opportuno studiare nell'ordine almeno questo e a seguire questo (se si preferisce, in un più completo formato PDF stampabile), sperabilmente seguiti da un testo di analisi numerica.

    Aggiungerei solo che, in casi del genere, un idioma generalmente caldeggiato in letteratura è il seguente:
    codice:
        pow(x*x,1./3.);
    Ultima modifica di M.A.W. 1968; 29-12-2015 a 16:18
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  5. #5
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    155
    Mi sembrava troppo semplicistico quanto da me ipotizzato, e infatti così era: intanto però ne ho imparata un'altra, e qualche link di materiale serio serve sempre!

    Grazie

  6. #6
    @ing82 @MItaly Grazie mille per l'interessamento e per l'aiuto!
    L'altro giorno alla fine ero riuscita a risolvere perché invece di scrivere pow(x,(2./3.)) ho usato l'operatore per la conversione double quindi pow(x,(double)(2/3)), perché ho pensato che il pow richiede solo double come argomenti -> pow(double,double) e infatti così non mi ha più dato problemi, il programma funzionava..Quello che non capisco è perché 2./3. non me lo riconosceva come double mentre double(2./3.) sì anche se in realtà lo sono entrambi....
    Ho provato anche con pow(-x, 2./3.) come hai detto tu @MItaly e anche così funziona, quindi grazie mille!

  7. #7
    Quote Originariamente inviata da martatos Visualizza il messaggio
    @ing82 @MItaly Grazie mille per l'interessamento e per l'aiuto!
    L'altro giorno alla fine ero riuscita a risolvere perché invece di scrivere pow(x,(2./3.)) ho usato l'operatore per la conversione double quindi pow(x,(double)(2/3)), perché ho pensato che il pow richiede solo double come argomenti -> pow(double,double) e infatti così non mi ha più dato problemi, il programma funzionava..Quello che non capisco è perché 2./3. non me lo riconosceva come double mentre double(2./3.) sì anche se in realtà lo sono entrambi....
    Se scrivi (double)(2/3) ottieni sempre 0: visto che 2 e 3 sono interi fa una divisione intera (e 2/3 in divisione intera dà 0), e poi converte il risultato a double; invece che NaN ottenevi sempre 1.
    Amaro C++, il gusto pieno dell'undefined behavior.

Tag per questa discussione

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2019 vBulletin Solutions, Inc. All rights reserved.