Discussioni su argomenti di Informatica

Regole del forum

Consulta il nostro regolamento e la guida per scrivere le formule
Rispondi al messaggio

[Caml] Conversione binario decimale

28/11/2021, 16:16

Salve a tutti. Sto studiando il linguaggio funzionale caml, in particolare sto cercando di risolvere questo esercizio: data una lista di interi contenente solo 0 e 1 che rappresentano un numero binario, convertire questo nel corrispondente in base 10. Ho pensato di ragionare così: prendo la lista, la inverto e man mano sommo tutti i valori moltiplicati per potenze di 2 crescenti, il problema è che non so come esprimerlo col codice, in particlare non so proprio come poter salvare la lista invertita e l'elevamento a potenza. Ho scritto questo codice, che naturalmente non funziona:

Codice:
let rec rev l = match l with
    [] -> []
  | h::t -> rev t @ [h];;

let rec f l = match l with
    [] -> 0
  | h::t -> let k = rev l in match k with
      [] -> 0
    | k::v -> k * 2 + f v;;


Sapreste aiutarmi a risolvere questo problema?

Re: [Caml] Conversione binario decimale

29/11/2021, 01:09

Non è necessario rovesciare la lista, pensa a come funziona la ricorsione.

Per l'elevamento a potenza o utilizzi una funzione ausiliaria con un parametro che rappresenta l'indice del passo corrente oppure puoi osservare che l'esponente corrisponde ad ogni passo alla lunghezza della coda.

Forse può esserti utile anche considerare che moltiplicare per $2^i$ equivale a shiftare a sinistra di $i$ posizioni.

Re: [Caml] Conversione binario decimale

29/11/2021, 11:02

Non serve calcolare le potenze di \(2\) esplicitamente né rovesciare la lista. Sia \(P[i]\) il valore della lista binaria corrispondente alle prime \(i\) cifre. Abbiamo ovviamente che \(P[0] = 0\). Inoltre \(P[N]\) (dove \(N\) è la lunghezza della tua lista) è il risultato che vuoi ottenere. Sia quindi che la \(i\)-esima cifra è uguale a \(c\), il valore di \(P[i]\) è quindi facilmente calcolabile a partire da \(P[i-1]\). Ti viene in mente un modo per farlo? Supponi di aver letto \(101_b = 5_d\) e di trovare un \(1\). Devi calcolare il risultato \(1011_b = 11\) a partire dai risultati parziali \(5\) e \(1\). Come fai?

Una volta che trovi la risposta non dovrebbe essere difficile convertire il tutto nel codice.

Testo nascosto, fai click qui per vederlo
Avrai bisogno di una funzione di supporto che memorizza il valore di \(P[i-1]\).


Un piccolo consiglio è comunque quello di provare ad usare dei nomi un po' più lunghi di f. Va forse bene per delle funzioni di supporto o locali alla tua funzione, ma in generale è più chiaro utilizzare nomi più descrittivi della funzione. In questo caso qualcosa come bin2dec per esempio.

Re: [Caml] Conversione binario decimale

29/11/2021, 11:33

Una piccola nota aggiuntiva sul tuo codice. Forse non ti hanno parlato di funzioni tail recursive, ma sono molto importanti per le performance nei linguaggi funzionali. Non conosco bene Caml, ma di solito nei linguaggi funzionali la inversione di una lista va scritta nel seguente modo:
Codice:
let reverse lst = reverseAcc [] lst

let rec reverseAcc acc lst =
   match lst with
   | [] -> acc
   | h::t = reverseAcc (h @ acc) t

Questo schema è molto comune in codici scritti con linguaggi funzionali perché mentre la tua soluzione utilizza \(O(N)\) spazio, quella che ho scritto viene convertita in un ciclo che ne usa solo una quantità costante.

Generare una lista di potenze di \(2\) non è difficile. Qualcosa del genere dovrebbe funzionare per esempio:
Codice:
let twoPowers n =
   let rec twoPowersHelper s n = if n > 0 then (s @ twoPowersHelper (2 * s) (n - 1)) else [] in
   twoPowersHelper 1 n

Tuttavia nel tuo caso è scomodo usare qualcosa del genere per due ragioni:
1. La funzione richiede il calcolo della lunghezza della tua listae quindi un ulteriore passaggio lungo di essa.
2. Se inizi a includere la lista in questo codice e passi alla versione tail recursive tornerai all'approccio decisamente migliore suggerito nel mio precedente post.

Re: [Caml] Conversione binario decimale

08/12/2021, 15:49

Grazie mille a tutti per l'intervento, sono riuscito a scrivere il codice in maniera molto semplice!
Rispondi al messaggio


Skuola.net News è una testata giornalistica iscritta al Registro degli Operatori della Comunicazione.
Registrazione: n° 20792 del 23/12/2010.
©2000— Skuola Network s.r.l. Tutti i diritti riservati. — P.I. 10404470014.