mercoledì 8 dicembre 2010

Possibili soluzioni delle esercitazioni 3 e 4


Ho messo in linea delle possibili soluzioni delle esercitazioni 3 e 4.
Per chiarimenti, o se ritenete la vostra soluzione da preferire, postate liberamente sul blog.
Soluzione esercitazione 3
Soluzione esercitazione 4

7 commenti:

  1. Salve professore e cari colleghi.
    Volevo condividere con voi un sistema alternativo per svolgere l'esercizio n.1 della esercitazione 4. Infatti è possibile utilizzare un puntatore a char, per estrarre i bytes della variabile unsigned long. Vediamo nel dettaglio il codice:


    char* p= (char*)&l;
    for(int i=0;i<4;i++)
    a[i]= p[i];

    Nel codice prima inizializziamo un puntatore a char e assegnamo a questo l'indirizzo di l facendo un cast a char* (dal momento che &l è un indirizzo di tipo unsigned long*). In seguito all'interno del ciclo copiamo i bytes dell'unsigned long nel vettore di char trattando il puntatore p come un vettore.

    Questa operazione è resa possibile grazie alla stretta somiglianza tra i vettori e i puntatori e grazie all'operazione di casting (char*)&l che ci permette di trattare l'indirizzo di l come l'indirizzo di una variabile di tipo char.

    RispondiElimina
  2. Anche questo e' un approccio corretto. Chi ha fatto Java o altri linguaggi si stupira' a vedere cose del genere ma ricordate che il C nasce come strumento per facilitare la vita a programmatori abituati al linguaggio macchina e quindi permette un contatto con l'hardware, e la memoria in particolare, che difficilmente si trova in altri linguaggi di alto livello.
    Non bisogna comunque eccedere in generale con codice poco chiaro o dipendente dalla macchina perche' quello che guadagnamo in efficienza lo perdiamo in facilita' di manutenzione del codice.

    RispondiElimina
  3. Devo ammettere che il primo esercizio è l'unico che mi ha messo in seria difficoltà, avendo fatto Java non ci sarei mai arrivato alla tua soluzione. Complimenti :P

    Dopo innumerevoli sforzi ho fatto qualcosa di più lunghetto ma finalmente funzionante.

    http://nopaste.info/3abeb7aba9.html

    Sostanzialmente l'algoritmo di risoluzione è simile a quello fornito dal professore, ma uso la funzione "carica" per riempire l'array (che dentro ha un for per generare gli indici).

    RispondiElimina
  4. @Gabriele: occhio che ci sono un paio di bug abbastanza tipici. Nella funzione carica il for fa 3 giri anziche' 4 (hai messo >0 invece di >=0) e nel main, dopo il for, devi stampare l'elemento 0 e non 3.
    Gli altri colleghi non se n'erano accorti? Vi ricordo che il blog e' zona franca (nei limiti della legge...) se avete appunti o obiezioni da fare, fatele liberamente!

    RispondiElimina
  5. Grazie fixato!
    Non l'avevo notato perchè avendo sbagliato il for, mi stampava due volte l'elemento 3.

    RispondiElimina
  6. Salve, desidero rivedere l'esercizio 3 della terza esercitazione.
    Nella soluzione il prof usa un ciclo for da i=2 to i=n/2 (n numero da verificare primo); Non sarebbe più corretto fermarsi alla parte intera della radice quadrata di n?
    Inoltre volevo rendere l'algoritmo più efficiente, e controllare che n%i=0 solo per i numeri primi minori di (int)(sqrt(n)), mi spiego con un esempio:
    Consideriamo n=29.
    Vorrei evitare il controllo di (n%i) per i=4 e tutti i numeri pari!
    Un aiuto?
    Grazie.
    Ornella

    RispondiElimina
  7. ornellavera01 ha certamente ragione riguardo la fine del ciclo. I controlli fra parte intera di radice di n ed n/2 necessariamente non avranno esito positivo e sono quindi inutili.
    Algoritmi efficienti per la verifica o il calcolo dei numeri primi ce ne sono in gran quantita'. Uno dei piu' semplici ed efficienti e' il cosiddetto Crivello di Eratostene. Quest'algoritmo, piu' che verificare la primalità di un singolo numero, in realta' calcola tutti numeri primi compresi fra 1 ed n. Vi riporto il testo di un esercizio a riguardo preso dal libro Deitel&Deitel e che vi invito a svolgere, io postero' una possibile implementazione a breve:

    Esercizio 4.29
    Un numero primo è un intero divisibile soltanto per 1 e per se stesso. Il crivello di Eratostene è un metodo per trovare i numeri primi. Funziona così:
    - Create un array con tutti gli elementi inizializzati a true. Gli elementi dell’array che hanno per indici dei numeri primi resteranno uguali a true. Tutti gli altri invece saranno impostati a false.
    - Partite dall’indice 2 (l’indice 1 è necessariamente primo), e ogni volta che trovate un elemento dell’array uguale a true, impostate a false tutti gli elementi il cui indice è multiplo dell’elemento trovato. Per l’elemento di indice 2, dovremo porre a false tutti gli elementi che si trovano dopo 2 e che sono multipli di 2, cioè tutti gli elementi di indice pari; ugualmente per l’elemento di indice 3, dovremo porre a false tutti gli elementi che hanno per indice un suo multiplo come 6, 9, 12, 15, etc... e così via.
    Quando avremo completato il procedimento, gli elementi dell’array che valgono ancora 1 avranno per indice un numero primo.
    Scrivete un programma che implementa il crivello di Eratostene su 1000 elementi, per determinare i numeri primi fra 1 e 999. Ignorate l’elemento 0 dell’array.

    RispondiElimina