Calcul entropie ocaml

Fermé
jeremux Messages postés 58 Date d'inscription samedi 23 octobre 2010 Statut Membre Dernière intervention 30 mai 2013 - 22 nov. 2010 à 20:40
jeremux Messages postés 58 Date d'inscription samedi 23 octobre 2010 Statut Membre Dernière intervention 30 mai 2013 - 24 nov. 2010 à 17:49
Bonjour, je dois calculer l'entropie d'un fichier vu comme une source de couple d'octets. Le problème de mon programme c'est qu'il retourne un résultat négatif! Je suis pourtant sur de la formule...Je suis dessus depuis hier soir. Quelqu'un aurait-il une idée sur mon erreur ?

Merci d'avance.
let entropie fichier = 
  let compteurs = Array.make 256 (Array.make 256 0) (* compteurs pour chacun des couples d'octets *)
  and somme = ref 0. (* compteur total de couple d'octets *) in
    (* Parcours du fichier pour compter les différents couple d'octets qu'il contient *)
  let  entree = open_in_bin fichier in 
  let res = ref (0,0.0) in
  begin
  	try
  		while true do
  			let n = input_byte entree in
  			let p = input_byte entree in
  			compteurs.(n).(p) <- compteurs.(n).(p) + 1; (* Comptabilisation de tel couple *)
  			somme := !somme +. 1. (* comptabilisation des couples *)
  		done;
  	with
  	    End_of_file ->
  			let tmp = ref 0.0 in
 			let ns = ref 0.0 in
 			for i=0 to 255 do
 				for j=0 to 255 do
 				ns := float_of_int(compteurs.(i).(j));
   					if compteurs.(i).(j)<>0 then (* le couple doit apparaitre au moins une fois *)
   						tmp := !tmp +. !ns*.(log(!ns)/.(log(2.)));
   				done;
 			done;
			res:=(int_of_float(!somme),((1./.log(2.))*.(log(!somme)))-.(!tmp/.(!somme)));
			close_in entree;
  end;
  !res;;
      
      
      
    

(**[usage ()] imprime sur la sortie standard l'utilisation normale du programme.*)
let usage () = 
  Printf.printf "Usage : %s <fichier>\n" Sys.argv.(0) ;
  Printf.printf "\t <fichier> = nom du fichier dont on veut l'entropie.\n" ;
  exit 1


(** Procédure principale.*)
let principal () =
  if Array.length Sys.argv <> 2 then
    usage () 
  else
    let nb,ent = entropie Sys.argv.(1) 
    in 
      Printf.printf "%d paires d'octets lu(s).\n" nb ;
      Printf.printf "Entropie = %f bits par seizet.\n" ent

	

let _ = principal ()


Pour creer l'exécutable: (sous linux) (si votre fichier se nomme entropie.ml)

ocamlc -c entropie.ml
ocamlc -o entropie entropie.cmo
./entropie <nom_du_fichier_a_calculer_lentropie>

Merci à tous!





A voir également:

2 réponses

bonsoir

d'abord je suis desole pour mon mal Francais; dans ce code je pense que vous faites votre premier faute en utilisant array d'array :
"let compteurs = Array.make 256 (Array.make 256 0) "
ici si vous utilisez cette expression; la somme de toutes elements de tableaux compteurs va devenir plus grande que la valeur de variable "somme"(c'est absurde car la somme des occurrence doit etre egale a la "somme"). Pour stocker les qte d'occurrence des couples vous devez utilisez une matrix. (Array.make_matrix compteures dim1 dim2 e et ici dim1=dim2=256 et e=0).

deuxiemment par exemple vous utilisez log(a)/log(2) pour calculer logarithme en base 2 de "a" mais en OCAML log(a) est le logarithme neperien de "a" pour calculer log2(a) vous devez utiliser log10(a)/log10(2) et ici log10(a) = logarithme de a en base 10
1
jeremux Messages postés 58 Date d'inscription samedi 23 octobre 2010 Statut Membre Dernière intervention 30 mai 2013 4
24 nov. 2010 à 17:49
Bonsoir et merci pour votre réponse.
Pourtant la somme me renvoie un bon résultat. Je vais voir avec les matrices.
Merci beaucoup!
0