DOMANDA Programmi con ricorsione C++

BAT

Moderatore
Staff Forum
Utente Èlite
22,948
11,581
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Strano, a parte il fatto che quando dai l'input devi usare il punto (non la virgola), cioè se x=2,5 tu devi inserire 2.5;
vedo che fai degli "include" spesso inutili, ma non dovrebbe essere un problema.
Concentrati sulla ricorsione: FUORI dalla funzione che calcola la potenza (se base=0.0 ed esponente=0 allora NON richiamare la funzione).
Nella funzione invece ti basta controllare i casi base (base=0.0 ritorna subito 0.0, esponente 0 ritorna subito 1.0) altrimenti fai la chiamata ricorsiva. Dentro la funzione ritorna dei double quindi NON ritornare 0 oppure 1, ritorna 0.0 e 1.0
Il codice che hai scritto mi sembra corretto, non capisco perché non ti funzioni. Ti allego il codice che ho scritto io e funziona (nota che l'ELSE prima della chiamata ricorsiva non è necessario, ma se ce lo metti fa lo stesso). Ho omesso il controllo di 0^0 (forma indeterminata).
C++:
#include <iostream>
using namespace std;

double potRic(double b, int k){
    // per la base 0 sarebbe meglio il test if(b>-0.000000000001 && b<000000000001)
    if(b==0.0) return 0.0; // se la base è 0 il risultato è 0
    if(k==0) return 1.0; // se l'esponente è 0 il risultato è 1
    return b*potRic(b,k-1);
}

int main() {
    char tasto = '1';
    double b;
    int k; // esponente
    cout << "\n----- INIZIO -----\n";
    do {
        cout << "\nInserisci la base --> ";
        cin >> b;
        cout << "\nInserisci l'esponente (intero) --> ";
        cin >> k;
        double ris = potRic(b, k);
        cout << "\n" << b << "^" << k << " = " << ris << endl;
        cout << "\nAncora? (1=SI, altro tasto=NO) --> ";
        cin >> tasto;
    } while(tasto != '0');
    cout << "\n------ FINE ------\n";
    return 0;
}
 
Ultima modifica:
  • Mi piace
Reazioni: MPG

MPG

Utente Attivo
544
4
L'errore era propio perchè scrivevo 2,5 invece di 2.5...
Il return -1 per 0^0 si puo' comunque mettere o è un errore?
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Come dice BAT non dovresti nemmeno richiamare la funzione in quel caso. Matematicamente 0^0 non è definita, non ha senso.
Se la fai con la calcolatrice ottieni 1.
 

BAT

Moderatore
Staff Forum
Utente Èlite
22,948
11,581
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Confermo quanto detto da @DispatchCode e aggiungo:
- da programma il controllo dell'input va fatto fuori, prima di richiamare la funzione
- in caso occorra necessariamente ritornare un valore per 0^0 devi ritornare un 1 ma devi essere cosciente che matematicamente non è corretto
- molte calcolatrici ritornano 0^0=1 in quanto, avendo la necessità di essere economiche (come prezzo intendo) non includono controllo più dettagliati; calcolatrici scientifiche moderne includono anche questi controlli, per esempio la Texas Instruments TI-30X Pro Mathprint (e la sorella minore Plus) per 0^0 ti restituiscono un errore di dominio (ossia ti fanno presente che l'input è fuori dal dominio di valori che può essere gestito)

Ricorda comunque che tu stai facendo esercizi sulla ricorsione, il controllo fatto fuori da programma è più che sufficiente.
 
Ultima modifica:

MPG

Utente Attivo
544
4
In quasto esercizio
"
Implementare la divisione intera ricorsiva (procedere per sottrazioni successive).
il suo funzionamento è abbastanza semplice : ogni volta ritorno 1 sommato alla divisione di (a-b)/b. Naturalmente non può essere usata con numeri negativi."

il prof ha usato il -1 e il -2 , non so a questo punto, anche per l'esercizio sopra potrebbe essere usato in virtu' di quanto mostrato qui sotto?

C++:
#include <iostream>

using namespace std;

int divisione(int a, int b);



    int main(){

    int a,b;


        do{

            cin>>a ;
            cout<<endl;

            cin>>b;
            cout<<endl;
        }while(a < 0 || b < 0);


       cout<< divisione(a,b);
    }


    int divisione(int a, int b){

        if (a == 0  && b == 0)

            return -1;

        if(b == 0)
            return -2;

        if (a<b)
            return 0;


        return 1+divisione(a-b,b);

    }
 

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
In quasto esercizio
"
Implementare la divisione intera ricorsiva (procedere per sottrazioni successive).
il suo funzionamento è abbastanza semplice : ogni volta ritorno 1 sommato alla divisione di (a-b)/b. Naturalmente non può essere usata con numeri negativi."

il prof ha usato il -1 e il -2 , non so a questo punto, anche per l'esercizio sopra potrebbe essere usato in virtu' di quanto mostrato qui sotto?

C++:
#include <iostream>

using namespace std;

int divisione(int a, int b);



    int main(){

    int a,b;


        do{

            cin>>a ;
            cout<<endl;

            cin>>b;
            cout<<endl;
        }while(a < 0 || b < 0);


       cout<< divisione(a,b);
    }


    int divisione(int a, int b){

        if (a == 0  && b == 0)

            return -1;

        if(b == 0)
            return -2;

        if (a<b)
            return 0;


        return 1+divisione(a-b,b);

    }
Assolutamente no. Se non avete fatto le eccezioni tanto vale ritornare -1 o 1 quando il divisore è 0 ebbasta.

Come ti hanno già detto gli altri il controllo va fatto all’esterno della funzione (cioè nel main) dove puoi fare quello che vuoi, come scrivere a schermo “Tentativo di divisione per 0” o quello che vuoi” (in questo esempio).

Cerca di indentare bene ‘sto codice...
 

MPG

Utente Attivo
544
4
Assolutamente no. Se non avete fatto le eccezioni tanto vale ritornare -1 o 1 quando il divisore è 0 ebbasta.

Come ti hanno già detto gli altri il controllo va fatto all’esterno della funzione (cioè nel main) dove puoi fare quello che vuoi, come scrivere a schermo “Tentativo di divisione per 0” o quello che vuoi” (in questo esempio).

Cerca di indentare bene ‘sto codice...

Quindi per te il prof sbaglia? Puo' essere che scrive cosi' per puro esercizio, non so che dire....
In pratica quando un calcolo è impossibile si mette -1 o -2.
 
Ultima modifica:

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Quindi per te il prof sbaglia? Puo' essere che scrive cosi' per puro esercizio, non so che dire....
Non è che sbaglia. Può pure ritornare quello che vuole.
Ma se io mi metto ad utilizzare la tua funzione, faccio una divisione per 0 e ho risultato -2 che vuol dire? 1/0 fa -2? Prova con la tua calcolatrice, ti risulta -2?
È per questo che esistono le eccezioni. In alternativa -1 può starci, più infinito pure, meno infinito ecc... ma -2...
 
  • Mi piace
Reazioni: MPG

MPG

Utente Attivo
544
4
Certo se fai l'operazione matematica sono d'accordo con te.
Le eccezioni non so cosa siano. Magari -2 è per differenziare n/0 da 0/0 che ovviamente non da' -1 ma entrambe le operazioni sono in realtà impossibili.
Ho trovato online questo:
"Since c does not support throwing exceptions when something was wrong, So programmers used the "return"as a way for a routine to sends some information to the parent routine that called it , it is considered to be an exit status , so mostly there was something of a convention that "0" meant success, a positive number meant minor problems, and a negative number meant some sort of failure. "
e questo
"The return(-1) in C used whenever user want a negative return from the method, it means the the method return false value. "
Alla fine quindi il return negativo (che sia -1 o -2) avrebbe la funzione di "qualcosa di sbagliato"
 
Ultima modifica:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Certo se fai l'operazione matematica sono d'accordo con te.
Le eccezioni non so cosa siano. Magari -2 è per differenziare n/0 da 0/0 che ovviamente non da' -1 ma entrambe le operazioni sono in realtà impossibili.
Ho trovato online questo:
"Since c does not support throwing exceptions when something was wrong, So programmers used the "return"as a way for a routine to sends some information to the parent routine that called it , it is considered to be an exit status , so mostly there was something of a convention that "0" meant success, a positive number meant minor problems, and a negative number meant some sort of failure. "
e questo
"The return(-1) in C used whenever user want a negative return from the method, it means the the method return false value. "
Alla fine quindi il return negativo (che sia -1 o -2) avrebbe la funzione di "qualcosa di sbagliato"

Si, è una convenzione utilizzata abitualmente per indicare che si è verificato un errore. Ci sta far tornare -1. Però il chiamante sa che deve trattare il -1 come errore.
Anche il return che fai nel main avrebbe lo stesso significato per il sistema operativo. (dico avrebbe, poiché a Windows ad esempio non interessa molto).
Se ci fai caso anche il compilatore in caso di errore torna un valore negativo.
 

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Certo se fai l'operazione matematica sono d'accordo con te.
Le eccezioni non so cosa siano. Magari -2 è per differenziare n/0 da 0/0 che ovviamente non da' -1 ma entrambe le operazioni sono in realtà impossibili.
Ho trovato online questo:
"Since c does not support throwing exceptions when something was wrong, So programmers used the "return"as a way for a routine to sends some information to the parent routine that called it , it is considered to be an exit status , so mostly there was something of a convention that "0" meant success, a positive number meant minor problems, and a negative number meant some sort of failure. "
e questo
"The return(-1) in C used whenever user want a negative return from the method, it means the the method return false value. "
Alla fine quindi il return negativo (che sia -1 o -2) avrebbe la funzione di "qualcosa di sbagliato"
Le eccezioni non sono altro che oggetti che vengono “lanciati” e poi vanno gestiti.
Praticamente:
C++:
int divisione(int a, int b) {
    if (b == 0)
        throw DivisionePerZero(); // DivisionePerZero è un oggetto che eredita da std::exception
    return a / b;
}

int main() {
    try {
        // blocco try in cui si possono ricevere le eccezioni
        divisione(5, 0); // questo fa "lanciare" DivisionePerZero
    }
    catch (std::exception e) {
        // e qui gestirle, magari scrivendo a schermo
        std::cout << e.what(); // what() ritorna il messaggio dell'eccezione
    }
}
È una soluzione abbastanza pulita e chiara
 

BAT

Moderatore
Staff Forum
Utente Èlite
22,948
11,581
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Il tuo professore sta ritornando dei valori convenzionali per gestire i possibili errori in input; come metodo è un po' "spiccio", tuttavia adatto al tipo di problema che state studiando. Ricorda sempre che qui il focus è su RICORSIONE, non sul controllo dell'input dell'utente. Questo significa che le tue funzioni (ricorsive) devono (o dovrebbero) ricevere sempre e solo parametri in input corretti. Nel caso della divisione dividendo e divisore si suppongono interi positivi, se non lo sono vanno "aggiustati" prima (ed il risultato va corretto di conseguenza). Quello che voglio dire è che se devi dividere 115 per -9, alla funzione devi passare i valori positivi 115 e 9, poi FUORI aggiusterai il risultato coerentemente con le regole dell'algebra (dividendo e divisore entrambi negativi generano un risultato positivo, se sono di segno discorde il risultato sarà negativo).
 
  • Mi piace
Reazioni: Andretti60

Andretti60

Utente Èlite
6,440
5,091
"Since c does not support throwing exceptions when something was wrong, ...
Non so chi abbia scritto quella castroneria, certo che è supportato, mediante l'invio di interrupt a cui si deve specificare una funzione da chiamare quando si ricevono, proprio come nel linguaggio assembler. L'implementazione dipende dal sistema operativo usato.

Ma come ti è stato detto da altri, questo non ha nulla a che vedere con quello che stai studiando adesso, ossia la ricursione. Lascia stare i casi “speciali”.
 

MPG

Utente Attivo
544
4
Scusate per il massimo numero in un array usando ricorsione è giusto cosi' o devo usare
return max(A[n], massimo(A, n-1))?
Ho trovato entrambe queste due righe per risolvere

C++:
int massimo(int A[], int n)
{
      if (n == 1)
        return A[0];
    return max(A[n-1], massimo(A, n-1));
}

int main()
{
    int A[] = {1, 4, 45, 6, -50, 10, 2};
    int n=7;
    cout <<  massimo(A, n);
    return 0;
}
 

rodhellas

Utente Èlite
1,522
427
CPU
Ryzen 5 3600
Dissipatore
GELID Phantom
Scheda Madre
MSI B450 Gaming Plus Max
HDD
500GB m.2 + 2TB HDD
RAM
16GB Corsair LPX 3000mhz
GPU
Gigabyte GTX 960 OC
Audio
Integrata
Monitor
SyncMaster 223BW
PSU
Antec HCG-520M
Case
Meshify C
Net
Gigabit Fastweb
OS
Windows 10 64bit
Scusate per il massimo numero in un array usando ricorsione è giusto cosi' o devo usare
return max(A[n], massimo(A, n-1))?
Ho trovato entrambe queste due righe per risolvere

C++:
int massimo(int A[], int n)
{
      if (n == 1)
        return A[0];
    return max(A[n-1], massimo(A, n-1));
}

int main()
{
    int A[] = {1, 4, 45, 6, -50, 10, 2};
    int n=7;
    cout <<  massimo(A, n);
    return 0;
}
Un array di 7 elementi va dalla posizione 0 alla..?
E il return max(A[n-1], massimo(A, n-1)) è orribile, in questo caso ti verrebbe fuori max(2, max(10, max(-50, max(6, max(45, max(4, max(1)))))));
 
Ultima modifica:

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili