IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Entropie d'un fichier


Sujet :

Caml

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 22
    Points : 17
    Points
    17
    Par défaut Entropie d'un fichier
    Bonjour à tous j'essaie de programmer quelque chose pour me retourner la taille et l'entropie d'un fichier, mais sans succès . J'obtient la taille mais pour l'entropie...j'obtient toujours not a number (nan).

    Quelqu'un peut-il m'aider?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    (**[entropie fichier] renvoie la valeur de l'entropie du fichier*)
    let entropie fichier = 
      let compteurs = Array.make 256 0 (* 256 compteurs pour chacun des octets *)
      and somme = ref 0. (* compteur total d'octets *) in
        (* Parcours du fichier pour compter les différents octets qu'il contient *)
      let  entree = open_in_bin fichier in (* canal ouvert en lecture *)
      let res = ref (0,0.0) in
      begin
      	try
      		while true do
      			let n = input_byte entree in
      			compteurs.(n) <- compteurs.(n) + 1;
      			somme := !somme +. 1.
      		done;
      	with
      	    End_of_file ->
      			let tmp = ref 0.0 in
     			let ns = ref 0.0 in
     			for i=0 to 255 do
       				ns := float_of_int(compteurs.(i));
       				tmp := !tmp +. !ns*.log(!ns);
     			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 octets lu(s).\n" nb ;
          Printf.printf "Entropie = %f bits par octet.\n" ent
     
     
     
    let _ = principal ()

    Pour ensuite utiliser il faut se rendre dans le dossier où se trouve la source et faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ocamlc -c entropie.ml
    ocamlc -o entropie entropie.cmo
    ./entropie <nom_du_fichier>

    Merci d'avance.

    Jeremux.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Ton code est très laid, tu utilises des références partout et c'est une horreur.

    SI tu veux un jour coder proprement, je te conseille d'essayer de limiter au *maximum* les références. Pour commencer, coder *sans* référence est sans doute une bonne idée (même si une fois qu'on sait se retenir on peut se permettre de ne pas le faire).

    Dans ta fonction entropie, il y a 4 références, dont deux (res et ns) sont trivialement inutiles. Par ailleurs, parmis ces 4 références, 3 ont un nom complètement incompréhensible ("res" pour résultat étant assez clair).

    Voilà un essai pour rendre ton code plus compréhensible; j'ai essayé de reproduire le même fonctionnement (donc en particulier aucun bug de ton code n'a été corrigé, mais j'en ai peut-être rajouté sans faire exprès) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    let entropie fichier =
      let occurences = Array.make 256 0 in
     
      let taille =
        let compteur = ref 0 in
        let entree = open_in_bin fichier in
        begin
          try
            while true do
              let n = input_byte entree in
              occurences.(n) <- occurences.(n) + 1;
              incr compteur
            done
          with Not_found -> close_in entree
        end;
        !compteur in
     
      let entropie =
        let ajoute entropie occ =
          let occ' = float_of_int occ in
          entropie +. occ' *. log occ' in
        Array.fold_left ajoute 0. occurences in
     
      let taille' = float_of_int taille in
      (taille,
       1. /. log 2. *. (log taille' -. entropie /. taille'))

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 22
    Points : 17
    Points
    17
    Par défaut
    Les variables a utiliser ont été imposé par le prof et également l’appellation, donc c'est raté pour la beauté. Merci quand meme.

    Sinon personne pour ce problème ?

    A chaque fois j'obtient -nan

  4. #4
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Bonsoir,

    Il y a même des commentaires nocifs (comme "canal ouvert en lecture" qui n'apporte strictement rien, on sait à quoi sert open_in_bin quand même). Pour le problème que tu rencontres, quelques questions en vrac :

    • Si une valeur du tableau reste nulle, que renvoie log fcount pour cette valeur ?
    • Si le fichier reçu en entrée est vide, que se passe-t-il ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    let entropie file =
      let tbl = Array.make 256 0 and ich = open_in_bin file in
      let rec loop sum =
        match try Some (input_byte ich) with End_of_file -> None with
        | None -> close_in ich; calc sum
        | Some byte -> tbl.(byte) <- tbl.(byte) + 1;
          loop (sum +. 1.)
      and calc sum =
        let res = 
          Array.fold_left (fun acc count ->
            let fcount = float count in
            acc +. fcount *. log fcount
          ) 0. tbl
         in (truncate sum, (log sum -. res /. sum) /. log 2.)
      in loop 0.
    Cordialement,
    Cacophrène

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Le bug vient du fait que, dans ton calcul de l'entropie, tu fais la somme de (occ *. log occ) même quand occ vaut 0, et que ça fait (0 * -infini), ce qui n'est pas bien sympathique. Il faut rajouter un test dans la boucle qui calcule "tmp" (si compteurs.(i) = 0, ne rien faire).

  6. #6
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Re,

    Citation Envoyé par bluestorm
    Le bug vient du fait que, dans ton calcul de l'entropie, tu fais la somme de (occ *. log occ) même quand occ vaut 0, et que ça fait (0 * -infini), ce qui n'est pas bien sympathique. Il faut rajouter un test dans la boucle qui calcule "tmp" (si compteurs.(i) = 0, ne rien faire).
    Tss tu parles trop Bluestorm.

    Cordialement,
    Cacophrène

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 22
    Points : 17
    Points
    17
    Par défaut
    Je veux jeter un coup d'oeil, merci!

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 22
    Points : 17
    Points
    17
    Par défaut
    Bon ben merci à tous problème résolu! J'avais en effet oublier que certaines cases du tableau étaient à 0.
    Et désolé pour ce code laid. ><

    A bientot et encore merci à tous!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Diminuer l'entropie d'un fichier
    Par Invité dans le forum Sécurité
    Réponses: 3
    Dernier message: 09/11/2014, 13h22
  2. fichier mappé en mémoire
    Par WinBernardo dans le forum Delphi
    Réponses: 7
    Dernier message: 01/12/2006, 09h38
  3. Réponses: 5
    Dernier message: 20/08/2002, 18h01
  4. Lire 1 bit d'un fichier en C
    Par Anonymous dans le forum C
    Réponses: 3
    Dernier message: 23/05/2002, 18h31
  5. Fichier PDOXUSRS.NET
    Par yannick dans le forum Paradox
    Réponses: 5
    Dernier message: 05/04/2002, 09h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo