Dubbio sul calcolo fattoriale in c
ho svolto questo esercizio
scrivere un algoritmo in linguaggio c:
-legge da tastiera tre umeri interi positivi x,y,z
-calcola il fattoriale di x e lo scrive in output
-calcola y^z e lo scrive in output
però ho un dubbio sullo svolgimento dell'esercizio io faccio così per il calcolo del fattoriale
solo che guardando esercizi simili di un esercizio vedo che spesso mettono
non dovrebbe ssere sbagliato ?visto che con i fattoriale appunto di moltiplica per il numero successivo minore , fino ad arrivare a 1?
grazie in anticipo
scrivere un algoritmo in linguaggio c:
-legge da tastiera tre umeri interi positivi x,y,z
-calcola il fattoriale di x e lo scrive in output
-calcola y^z e lo scrive in output
#include <stdio.h> #include <stdlib.h> int main(){ int x , y, z , fatt, prod ,a; prod=1; printf("inserisci un numero:"); scanf("%d" , &x); printf("inserisci un numero:"); scanf("%d" , &y); printf("inserisci un numero:"); scanf("%d" , &z); for (fatt=x ;fatt>0; fatt--){ prod=prod*fatt; } printf("il fattoriale di x e': %d\n" , prod); for(a=1 ; a<z ; a++){ prod=prod*y; } printf("y elevato a z vale:%d\n" , prod); return 0; }
però ho un dubbio sullo svolgimento dell'esercizio io faccio così per il calcolo del fattoriale
for (fatt=x ;fatt>0; fatt--){ prod=prod*fatt; } printf("il fattoriale di x e': %d\n" , prod);
solo che guardando esercizi simili di un esercizio vedo che spesso mettono
(fatt=1 ;fatt<=x; fatt++)
non dovrebbe ssere sbagliato ?visto che con i fattoriale appunto di moltiplica per il numero successivo minore , fino ad arrivare a 1?
grazie in anticipo
Risposte
Allora andiamo per punti:
1)Lettura da tastiera OK
2)Calcolare fattoriale e stampa in output
Quasi
Non hai inizializzato prod
Poi un piccolo appunto
Perché usi una variabile d'appoggio fatt se la variabile x ti serve solo per il calcolo del fattoriale?
Non c'è nessun errore ma quando non ti importa di mantenere in memoria il valore iniziale di una variabile puoi evitare di usarne una temporanea.
Sarebbe stato utile l'utilizzo di fatt se nella printf avessi stampato anche la x(cosa che rende il codice sicuramente più utile/leggibile)
*) Per quanto riguarda la tua domanda
Il calcolo del fattoriale lo puoi fare sia dal basso che dall'alto.
Infatti
$ 5*4*3*2*1 = 1*2*3*4*5 = 5! $
3)Calcolo y^z e stampa in output
Errore
Stai usando prod che al momento contiene il fattoriale di x
Inoltre c'è un errore nel for, ti sei perso un ciclo
Ti ricordo inoltre che ci sono anche le librerie come math.h per il calcolo della potenza
1)Lettura da tastiera OK
2)Calcolare fattoriale e stampa in output
Quasi
Non hai inizializzato prod
Poi un piccolo appunto
Perché usi una variabile d'appoggio fatt se la variabile x ti serve solo per il calcolo del fattoriale?
Non c'è nessun errore ma quando non ti importa di mantenere in memoria il valore iniziale di una variabile puoi evitare di usarne una temporanea.
Sarebbe stato utile l'utilizzo di fatt se nella printf avessi stampato anche la x(cosa che rende il codice sicuramente più utile/leggibile)
*) Per quanto riguarda la tua domanda
Il calcolo del fattoriale lo puoi fare sia dal basso che dall'alto.
Infatti
$ 5*4*3*2*1 = 1*2*3*4*5 = 5! $
3)Calcolo y^z e stampa in output
Errore
Stai usando prod che al momento contiene il fattoriale di x
Inoltre c'è un errore nel for, ti sei perso un ciclo
Ti ricordo inoltre che ci sono anche le librerie come math.h per il calcolo della potenza
"JackMek":
Allora andiamo per punti:
1)Lettura da tastiera OK
2)Calcolare fattoriale e stampa in output
Quasi
Non hai inizializzato prod
ho inzialiazzato prod , ho posto all'inzio prod=1 , o è sbagliato?
ps preferisco non usare la libreria math , così mi viene più spontaneo fare i ragionamenti piuttosto che avere la formula già pronta
io l'ho modificato così
ho modificato il ciclo for , e ho ho aggiunto un'altra variabile che ho inzializzato e che ho messo al posto di prod , perchè senò non avrei saputo come mettere la y (di questo punto sono meno sicuro però) , che poi devo stampare
grazie mille per l'aiuto
io l'ho modificato così
ho modificato il ciclo for , e ho ho aggiunto un'altra variabile che ho inzializzato e che ho messo al posto di prod , perchè senò non avrei saputo come mettere la y (di questo punto sono meno sicuro però) , che poi devo stampare
#include <stdio.h> #include <stdlib.h> int main(){ int x , y, z , fatt, prod ,a ,b; b=1; prod=1; printf("inserisci un numero:"); scanf("%d" , &x); printf("inserisci un numero:"); scanf("%d" , &y); printf("inserisci un numero:"); scanf("%d" , &z); for (fatt=x ;fatt>0; fatt--){ prod=prod*fatt; } printf("il fattoriale di x e': %d\n" , prod); for(a=0 ; a<z ; a++){ b=b*y; } printf("y elevato a z vale:%d\n" , b); return 0; }
grazie mille per l'aiuto
Mi era sfuggito prod=1
Puoi inizializzare una variabile direttamente quando la dichiari
Invece di
Puoi fare
Per quanto riguarda il secondo ciclo for ora funziona.
Ma ti bastava inizializzare nuovamente prod prima del secondo ciclo for senza introdurre una nuova variabile
Puoi inizializzare una variabile direttamente quando la dichiari
Invece di
int prod; prod = 1;
Puoi fare
int prod = 1;
Per quanto riguarda il secondo ciclo for ora funziona.
Ma ti bastava inizializzare nuovamente prod prima del secondo ciclo for senza introdurre una nuova variabile
Ciao!
Per il fattoriale puoi usare la ricorsione ad esempio così
Anche per l'esponenziale puoi usare questo approccio
Per il fattoriale puoi usare la ricorsione ad esempio così
#include <stdio.h> int fatt(int i){ if(i==1 || i == 0) return 1; return i*fatt(i-1); } int main(){ printf("%d",fatt(5)); return 0; }
Anche per l'esponenziale puoi usare questo approccio

"Cronovirus":
Ciao!
Per il fattoriale puoi usare la ricorsione ad esempio così
#include <stdio.h> int fatt(int i){ if(i==1 || i == 0) return 1; return i*fatt(i-1); } int main(){ printf("%d",fatt(5)); return 0; }
Anche per l'esponenziale puoi usare questo approccio
Il tuo codice presenta un bug enorme: non controlli che il valore di \(i\) sia maggiore di \(0\). Se chiami fatt(-1) il tuo codice va avanti all'infinito. Comunque non vi sono reali vantaggi nell'usare la ricorsione, specialmente nel C.
Tra l'altro il reale problema di tutti i codici che implementano il fattoriale usando variabili int è che 13! > INT_MAX quindi un programma di questo tipo è più un esempio che altro (sarebbe appropriato comunque controllare che \(i < 13\) per evitare risultati senza alcun senso). Usando un double probabilmente non si è in grado di lavorare neanche con tutti gli interi minori di 256 e vi sono perdite di precisioni già a valori piuttosto bassi.
Se per l'esponenziale usi la ricorsione tanto vale usare la fast exponentiation. http://en.wikipedia.org/wiki/Exponentiation_by_squaring
"vict85":
[quote="Cronovirus"]Ciao!
Per il fattoriale puoi usare la ricorsione ad esempio così
#include <stdio.h> int fatt(int i){ if(i==1 || i == 0) return 1; return i*fatt(i-1); } int main(){ printf("%d",fatt(5)); return 0; }
Anche per l'esponenziale puoi usare questo approccio
Il tuo codice presenta un bug enorme: non controlli che il valore di \(i\) sia maggiore di \(0\). Se chiami fatt(-1) il tuo codice va avanti all'infinito. Comunque non vi sono reali vantaggi nell'usare la ricorsione, specialmente nel C.
Tra l'altro il reale problema di tutti i codici che implementano il fattoriale usando variabili int è che 13! > INT_MAX quindi un programma di questo tipo è più un esempio che altro (sarebbe appropriato comunque controllare che \(i < 13\) per evitare risultati senza alcun senso). Usando un double probabilmente non si è in grado di lavorare neanche con tutti gli interi minori di 256 e vi sono perdite di precisioni già a valori piuttosto bassi.
Se per l'esponenziale usi la ricorsione tanto vale usare la fast exponentiation. http://en.wikipedia.org/wiki/Exponentiation_by_squaring[/quote]
Carissimo,
non sapevo che questo forum fosse un luogo dove ottenere codice a richiesta. Mi sembrava chiaro che il nostro amico qui avesse un problema concettuale più che di avere un codice testato e pronto da vendere. Io ho solo proposto un'altra maniera di farlo. E' chiaro che il mio codice non fa tutti i controlli del caso ma quelli te li puoi fare da solo. Che poi.. se vogliamo fare i puntigliosi il problema non dovrebbe essere nel codice quanto in chi lo usa: il fattoriale di un numero negativo non è definito.
Se vuoi ottimizzarlo puoi usare la programmazione dinamica, oltre che cercando su google
Mai detto che questo forum sia un posto dove ottenere codici a richieste, tra l'altro tu sei l'unico che ha fornito un codice (seppur l'autore della discussione avesse già trovato la sua risposta). La mia risposta voleva solo porre alcune problematiche importanti che sono comuni a molti codici di questo tipo. Inoltre non sono un amante della ricorsione, quindi mi sono forse fatto prendere un po' la mano.
In ogni caso se il fattoriale di un numero negativo non è definito allora il tuo codice dovrebbe tenerne conto, per esempio potresti usare un unsigned oppure darne una definizione tu[nota]Per esempio decidere che \(\displaystyle (-n)! = -(n!) \) oppure porlo a \(\displaystyle 0 \). Nel secondo caso ti bastava cambiare il tuo if in un (i <=1) per eliminare il bug.[/nota]). Avere una funzione che per determinati tipi di input produce un ciclo infinito non è mai positivo o accettabile. Inoltre l'utente potrebbe fare il fattoriale di qualcosa che viene fuori da altre operazioni e non rendersi conto che i valori che escono da quelle funzioni sono negativi. Certo si tratta di un errore del codice complessivo ma una funzione come quella che hai scritto non aiuta a trovare il problema.
La tua proposta di usare la programmazione dinamica per ottimizzare una operazione risolvibile con complessità logaritmica sinceramente mi lascia piuttosto perplesso. L'unica cosa che mi viene in mente è che tu intenda che puoi usare la programmazione dinamica per trovare la successione di operazioni minima per calcolare una determinata potenza. È un problema interessante, Knuth né parla ampiamente nel suo “The Art of Computer Programming”, ma cercare questa successione richiede una complessità maggiore di calcolare direttamente la potenza. E usarla per costruire un albero mi pare uno spreco di risorse considerando che ti richiede di caricare l'albero (l'operazione più costosa che esista), ricercare la soluzione e fare le operazioni. Inoltre la fast exponentiation non richiede molte più operazioni (in rapporto a n) e l'uso di un albero non mi sembra risulti comunque ottimale (se non ricordo male Knuth faceva un esempio nel secondo volume).
Riguardo al fattoriale sono piuttosto sicuro che in generi si ottimizzi calcolando la funzione gamma o meglio approssimando la funzione gamma. Anche numericamente penso che abbiano risultati migliori quando il fattoriale non sia più esprimibile in maniera esatta.
In ogni caso se il fattoriale di un numero negativo non è definito allora il tuo codice dovrebbe tenerne conto, per esempio potresti usare un unsigned oppure darne una definizione tu[nota]Per esempio decidere che \(\displaystyle (-n)! = -(n!) \) oppure porlo a \(\displaystyle 0 \). Nel secondo caso ti bastava cambiare il tuo if in un (i <=1) per eliminare il bug.[/nota]). Avere una funzione che per determinati tipi di input produce un ciclo infinito non è mai positivo o accettabile. Inoltre l'utente potrebbe fare il fattoriale di qualcosa che viene fuori da altre operazioni e non rendersi conto che i valori che escono da quelle funzioni sono negativi. Certo si tratta di un errore del codice complessivo ma una funzione come quella che hai scritto non aiuta a trovare il problema.
La tua proposta di usare la programmazione dinamica per ottimizzare una operazione risolvibile con complessità logaritmica sinceramente mi lascia piuttosto perplesso. L'unica cosa che mi viene in mente è che tu intenda che puoi usare la programmazione dinamica per trovare la successione di operazioni minima per calcolare una determinata potenza. È un problema interessante, Knuth né parla ampiamente nel suo “The Art of Computer Programming”, ma cercare questa successione richiede una complessità maggiore di calcolare direttamente la potenza. E usarla per costruire un albero mi pare uno spreco di risorse considerando che ti richiede di caricare l'albero (l'operazione più costosa che esista), ricercare la soluzione e fare le operazioni. Inoltre la fast exponentiation non richiede molte più operazioni (in rapporto a n) e l'uso di un albero non mi sembra risulti comunque ottimale (se non ricordo male Knuth faceva un esempio nel secondo volume).
Riguardo al fattoriale sono piuttosto sicuro che in generi si ottimizzi calcolando la funzione gamma o meglio approssimando la funzione gamma. Anche numericamente penso che abbiano risultati migliori quando il fattoriale non sia più esprimibile in maniera esatta.