Problemi da principiante! overflow c++

di il
15 risposte

Problemi da principiante! overflow c++

Buon giorno!
sono bruno e come si vede dal titolo mi sono affacciato da poco alla programmazione.
sto seguendo un videocorso sul c++11 del professor fabrizio camuso e andando a ricopiare un suo esercizio sul
if else mi sono imbattuto su degli strani risultati.
riporto il codice e poi proseguo con la descrizione:
  
#include <iostream>
#include <limits>
//#include <cstdint>
using namespace std;


 int main ()
{///  A definizione e inizializzazione strutture dati
 ///  B acquisizione dei dati INDISPENSABILI (INPUT)
 ///  C elaborazione dei dati ( calcoli  e processi )
 ///  D comunicazione dei risultati (OUTPUT)

 int n1=0, n2=0, n3=0;

/* ///input dati separato con INVIO per ogni dato immesso

 cout << "\n inserisci n1 \n";
 cin>> n1;

 cout << "\n inserisci n2 \n";
 cin>> n2;

 cout << "\n inserisci n3 \n";
 cin>> n3 ;

 cout << "\n dati letti :   \n" << "n1:"
      << n1 << "n2:" << n2 << "n3:" << endl;*/

 /// inserimento  dati sequenziali (senza invio)

 cout << " inserire tre numeri interi separati da uno spazio :";
 cin >> n1 >> n2 >> n3;


 cout << "\n dati letti :\n" << " n1 :"
      << n1 << " n2 :" << n2 << " n3 :" << n3 << endl;

      /// elaborazione

      /// calcolo della media primo modo
  int somma =0;
  somma = n1+n2+n3;
  int media1 = somma /3;    /// divisione senza decimali


   /// calcolo media secondo modo

   int media2 = (n1+n2+n3) /3;

   /// calcolo media  num 3

   double media3 = (n1+n2+n3) /3; /// ATTENZIONE
            /// IL CALCOLO VIENE ESEGUITO FRA INTERI E VIENE
            /// RESTITUITA LA PARTE INTERA ALLA VARIABILE DOUBLE

  /// soluzione con forzatura di almeno uno dei membri a double
  long long media4 = (n1+n2+n3) /3; /// 3.0 è stato forzato a double per ottenere i decimali



 cout<< "media1 :  " << media1 << endl;
 cout<< "media2 :  " << media2 << endl;
 cout<< "media3 :  " << media3 << endl;
 cout<< "media4 :  " << media4 << endl;


cout << "double  :" <<sizeof(double) << endl;
cout << "float  :" << sizeof(float)<< endl;
cout << "int  :" << sizeof(int)<< endl;
cout << "long long int  :" << sizeof(long long int)<< endl;

cout<< "lmax  :" << LONG_MAX << endl;
cout<< "lmin  :" << LONG_MIN << endl;
cout<< "int_max :" << INT_MAX << endl;
cout<< "int_min :" << INT_MIN << endl;

 return 0;

}
Quando mi sono trovato a fare la prova del codice scritto, facendo lo stesso stress test del video e scrivendo per tre volte il numero 1miliardo
per testare i limiti di overflow. la variabile media4, che inizialmente è partita come un double , mi dava il medesimo numero della variabile media3.
ho provato a cambiarne il tipo , controllando anche con il sizeof la capacità, e mi ritrovo ad avere sempre un numero che non rientra
nel range di capacità, cosa che invece dovrebbe avvenire con i tipi long long e (credo anche ) double.
eppure fra l'architettura usata nel video e quella del mio pc i byte in uso per i vari tipi corrispondono.
vorrei capire dove sta l'inghippo.
inoltre , visto che sono nuovo e devo prendere ancora confidenza con le varie funzionalità di questa pagina vi chiedo: come si usa il pulsante
code? nel senso che: ho provato a premerlo quando ho ricopiato il codice ma non ne capisco sia l'uso che la necessità.
abbiate pazienza.
grazie in anticipo.

15 Risposte

  • Re: Problemi da principiante! overflow c++

    Se sommi 3 volte un miliardo (3 miliardi) vai oltre le capacità di un int (e le variabili n1 n2 n3 sono int, di conseguenza anche la somma). Per questo il risultato sarà falsato.
  • Re: Problemi da principiante! overflow c++

    Grazie per essere stato cosi veloce.
    infatti la capacità dell'int era gia " compreso nel prezzo" che non ce la fa. per questo ne ho cambiato il tipo ,
    passando al double , al long e infine , cosa che mi ha (con molto piacere direi ) costretto a chiedere info a questo forum, al long long.
    eppure troco sempre dei valori sballati. con media4 impostato come long long , mi salta fuori: -461655765. chiaro esempio di overflow.
    eppure non dovrebbe...
  • Re: Problemi da principiante! overflow c++

    Non ci siamo capiti ... il problema non è il tipo del contenitore del risultato (long long media4) ma delle 3 variabili con cui fai la somma

    (n1+n2+n3)

    E'

    (n1+n2+n3)

    che dà il problema perché il risultato di questa somma è più grande di un intero.
  • Re: Problemi da principiante! overflow c++

    Forse ho letto con troppa precipitosità la tua risposta.
    mi stai dicendo che non devo modificare la variabile media4 bensi n1 n2 n3? nel video che stavo seguendo si parlava infatti di come forzare il
    risultato per ottenere dei numeri decimali ponendo a double media4 e di come un tipo di variabile può influire sul risultato ; solo che ,per ottenere la media corretta e senza overflow non ha effettuato nessuna modifica su n1 n2 n3...
  • Re: Problemi da principiante! overflow c++

    Invece devi effettuare un cast di almeno una delle variabili per il corretto risultato

    long long media4 = ((long long)n1+n2+n3) /3;
  • Re: Problemi da principiante! overflow c++

    Ok chiarito il concetto, e sicuramente sono stato anche io a fare qualche pasticcio nella comprensione del video.
    trovo comunque strano, benchè accetto la tua spiegazione, che la somma di variabili int (con segno e capienza limitata ) non possa
    essere effettuata in un contenitore (long o long long ) intero con segno e capienza maggiore.
    grazie.
    spero di potere approfittare ancora
  • Re: Problemi da principiante! overflow c++

    brunobaglieri ha scritto:


    trovo comunque strano, benchè accetto la tua spiegazione, che la somma di variabili int (con segno e capienza limitata ) non possa essere effettuata in un contenitore (long o long long ) intero con segno e capienza maggiore
    "Questa è Sparta!"
    Scherzi a parte: il compilatore non può sapere cosa conterranno quelle variabili e di certo non possiamo scomodare 64bit se magari contengono valori molto bassi.
  • Re: Problemi da principiante! overflow c++

    brunobaglieri ha scritto:


    trovo comunque strano ... che la somma di variabili int (con segno e capienza limitata ) non possa
    essere effettuata in un contenitore (long o long long ) intero con segno e capienza maggiore.
    Ancora non ci siamo capiti ...

    Al compilatore NON importa (solamente) quale sia il tipo di contenitore "finale". Quindi non importa che sia un long long ma quello che è IMPORTANTE è il tipo dei singoli operandi nell'espressione. Il compilatore esamina la parte dell'espressione

    (n1+n2+n3)

    e ottiene il codice che ne fa la somma SENZA sapere che il tutto finirà in un long long.

    Per memorizzare questa somma PARZIALE, dato che tutte le variabili sono intere, userà un intero TEMPORANEO in cui il risultato però NON potrà essere corretto. E da qui in poi l'errore.

    Ti è chiaro adesso?

    (Molte cose i "video" non le dicono o non le sanno ... diffida da questi "tutorial" ...)
  • Re: Problemi da principiante! overflow c++

    Fatico a comprenderne il senso. cioè se fra un int un long e un long long la differenza sta solo nella capienza ( magari dietro le quinte non è proprio cosi) usando un contenitore piu grande (dello stesso tipo ) dovrei poterlo usare senza problemi. giustamente il compilatore non sa in partenza cosa verrà inserito e una volta compreso che il tipo è lo stesso dovrebbe poterlo contenere se " la ciotola è più grande"; proprio per non andare a scomodare dei bit in maniera poco proficua quando crei una variabile in partenza e non avere problemi di capienza alla fine.
    poi però se "sparta è sparta... ce ne facciamo una ragione". avro sicuramente modo di capire più avanti come gestire le risorse in maniera ottimale.
    thanks.
    oregon ho visto che che nel frattempo mi hai risposto, per favore non aggredirmi chissà quante ancora ne devo prendere di bastonate prima di fare del codice come dio comanda.
    grazie
  • Re: Problemi da principiante! overflow c++

    Ma chi ti aggredisce??

    Con l'esempio delle ciotole, pensa di avere 3 ciotole da 2 litri e volerne versare i contenuti in un'altra ciotola SENZA usare la ciotola finale.
    Verrà usata una ciotola temporanea sempre da 2 litri in cui i 3 litri delle altre ciotole non ci stanno. E le operazioni non potranno concludersi.
  • Re: Problemi da principiante! overflow c++

    In senso mataforico intendevo. capisco che , per voi che mi rispondete i concetti sono di facile lettura; non per me che li devo masticare e poi digerire per poterli usare. mi viene da sorridere perchè dopo la digestione l'altra operazione è.... chissà che codici di programma scriverò?!
    se avete qualche suggerimento per potere approfondire la conoscenza del linguaggio, che integrino i tutorial che sto seguendo, è bene accetto.
    vi ringrazio per il momento.
    è stato un piacere entrare in questa comunità ed è stato altrettanto piacevole scambiare due parole con voi.
  • Re: Problemi da principiante! overflow c++

    La cosa che si raccomanda sempre e a tutti è studiare dai LIBRI.

    Esistono tanti libri (e ne sono stati suggeriti tanti anche in questo forum), di base e più avanzati, da poter studiare.

    E' necessario farlo, sia per la parte teorica che per gli esercizi. E poi tanto tempo e pazienza.
  • Re: Problemi da principiante! overflow c++

    @brunobaglieri LASCIA PERDERE INTERNET se vuoi imparare a programmare!

    1) a meno di motivi specifici, LASCIA STARE il C++! Se e' per hobby MOOLTO MEGLIO Python

    2) COMPRA LIBRI E STUDIA SUI LIBRI.

    Ti si potrebbe fare una papardella lunga un chilometro del perche' BISOGNA USARE I LIBRI, ma ci arrivi anche da solo sul PERCHE' SI DEVE STUDIARE SUI LIBRI!

    Perche' NON il C++?:
    innanzitutto perche' tu non stai studiando C++ ma il C, un linguaggio di programmazione PROCEDURALE.
    Il C++ e' un ENORME SOVVRAINSIEME del C, con una filosofia di programmazione (quella ad oggetti) TOTALMENTE DIVERSA dalla programmazione procedurale.

    Ma e' un linguaggio che GRATTA IL FERRO cioe' comandi direttamente il processore ed accedi direttamente alle risorse hardware.
    Questo vuol dire, in particolare, che se sbagli qualcosa (nel 99.9% dei casi per chi e' alle prime armi) devi avere il pelo sullo stomaco per capire, a partire dalla segnalazione dell'errore ASSOLUTAMENTE CRIPTICA che cosa hai combinato.

    Poi ha tutta una serie di altre rogne rognose come l'allocazione della memoria, difficolta' di trovare librerie, poche librerie per fare cose interessanti, ecc...

    In pratica e' un linguaggio che ha un suo ben definito campo di utilizzo, e richiede la pelliccia completa per poterlo controllare

    MOOLTO meglio Python: MOOLTO piu' semplice.
    - non hai il problema della memoria (se la gestisce lui)
    - non hail problema del tipo delle variabili: si arrangia lui a fare le conversioni del caso
    - ha un SACCO di librerie interessanti: salle cose piu' banali alle reti neurali, algoritmi genetici e qualunque strana cosa ti venga in testa
    - hai un sacco di documentazione, e ci sono UN SACCO DI LIBRI.
    - puoi programmare SIA proceduralmente SIA ad oggetti


    Forse non l'ho ancora detto, ma CONVIENE STUDIARE SUI LIBRI!
  • Re: Problemi da principiante! overflow c++

    Grazie per il consiglio di studiare sui libri. in realtà personalmente sono convinto che, per quanto giusto e corretto e non deve mancare , lo studio sui libri può essere snellito con qualche tutorial. in realtà sono convinto anche che lo studio su libro deve essere affettuato almeno con due testi differenti.
    inoltre entra in gioco anche il tipo di memoria che ognuno di noi possiede. nel senso che c'è chi memorizza più velocemente a vista e chi memorizza a udito ( ecco l'utilità del tutorial) , componente che non sottovaluterei in un percorso di apprendimendo. ho iniziato con c++ perchè me lo hanno presentato come un mattone... ergo se arriverò a comprenderne a fondo (tempo ce ne vorrà) i suoi meccanismi e dovrò farmi crescere il pelo ok! sono pronto. magari mi servirà tanto aminexil ma credo che sia alla mia portata. ho comunque alle spalle un diploma da perito elettronico e telecomunicazioni che , per quanto lo abbia usato poco, faccio l'elettricista, mi da un background non proprio da ultimo arrivato. chiaro che avendo iniziato solo da 4 mesi non pretendo nulla da me.
    non ho mai frequentato forum e quindi non so ancora come muovermi , nel senso se trattarlo come una chat o si può restare in sospeso riprendendo in un altro momento, senza essere maleducati.
    quindi per il momento vi saluto. e grazie ancora
Devi accedere o registrarti per scrivere nel forum
15 risposte