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 :

Ocaml Somme Des diviseurs d'un entier


Sujet :

Caml

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Ocaml Somme Des diviseurs d'un entier
    Bonjour,
    J'essaye de faire un fonction qui me permet d'additionner les diviseurs d'un entier comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let rec somme n =
      if (n mod n-1 =0) then (n-1) + somme (n-2);
      if n = 1 then 1;;
    Mais je reçois l'erreur qui suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Characters 43-62:
        if (n mod n-1 =0) then (n-1) + somme (n-2);
                               ^^^^^^^^^^^^^^^^^^^
    Error: This expression has type int but an expression was expected of type
             unit
    Comment je pourrai changer le type unit ? j'ai pas compris pourquoi il prends en unit alors que la recursivité va vers l'int.
    Merci de m'aider

  2. #2
    Membre actif
    Avatar de Ptival
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2004
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2004
    Messages : 70
    Points : 276
    Points
    276
    Par défaut
    Quant à la réponse :
    est un sucre syntaxique pour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if cond then value else ();;
    En effet, dans un langage fonctionnel, que la condition soit évaluée à true ou à false, il faut renvoyer une valeur d'un unique type. Si tu oublies le else, il faut bien trouver une valeur, donc OCaml avise que tu voulais utiliser le type (), qui est un peu le seul pour lequel il sait créer une valeur bidon.

    Dans tous les autres cas, on écrit toujours une expression complète :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if cond then valuetrue else valuefalse;;
    où valuetrue et valuefalse doivent avoir le même type, qui est de ce fait le type de l'expression if en entier.

    Ici, tu veux renvoyer des entiers, donc, en suivant ton style, faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    let rec somme n =
      if n mod n - 1 =0
      then (n-1) + somme (n-2)
      else if n = 1
      then 1
      else 0
    Ceci étant, je pense que tu t'y prends mal pour ce que tu veux faire :
    - "n mod n - 1" se parenthèse probablement "(n mod n) - 1", et renvoie toujours 0. Peut-être que tu voulais écrire "n mod (n - 1)", cependant, ce n'est pas un progrès puisque cela renvoie toujours 1...
    - Si tu souhaites à sommer les éléments de 0 à n inclus, une bonne façon naïve de faire est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    let rec somme n =
      if n = 0
      then 0
      else n + somme (n - 1)
    Peut-être que tu peux en dire plus sur les raisons qui t'ont fait utiliser un modulo, et ce que tu voulais vraiment calculer.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Ptival Voir le message
    Quant à la réponse :
    est un sucre syntaxique pour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if cond then value else ();;
    En effet, dans un langage fonctionnel, que la condition soit évaluée à true ou à false, il faut renvoyer une valeur d'un unique type. Si tu oublies le else, il faut bien trouver une valeur, donc OCaml avise que tu voulais utiliser le type (), qui est un peu le seul pour lequel il sait créer une valeur bidon.

    Dans tous les autres cas, on écrit toujours une expression complète :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if cond then valuetrue else valuefalse;;
    où valuetrue et valuefalse doivent avoir le même type, qui est de ce fait le type de l'expression if en entier.

    Ici, tu veux renvoyer des entiers, donc, en suivant ton style, faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    let rec somme n =
      if n mod n - 1 =0
      then (n-1) + somme (n-2)
      else if n = 1
      then 1
      else 0
    Ceci étant, je pense que tu t'y prends mal pour ce que tu veux faire :
    - "n mod n - 1" se parenthèse probablement "(n mod n) - 1", et renvoie toujours 0. Peut-être que tu voulais écrire "n mod (n - 1)", cependant, ce n'est pas un progrès puisque cela renvoie toujours 1...
    - Si tu souhaites à sommer les éléments de 0 à n inclus, une bonne façon naïve de faire est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    let rec somme n =
      if n = 0
      then 0
      else n + somme (n - 1)
    Peut-être que tu peux en dire plus sur les raisons qui t'ont fait utiliser un modulo, et ce que tu voulais vraiment calculer.
    Tout d'abord , Merci pour ta reponse.
    Donc ce que j'ai compris c'est que je dois renvoyer impérativement un entier soit 0 si les deux conditions ne sont pas verifiés , mais moi je veux avoir une recursivité par rapport à n qui veux dire que a chaque fois que je prends n (entier) je le divise par n-1 et je vois si le modulo = 0 et la je somme le n-1 qui est un diviseur du nombre n et ensuite sommer tous les diviseurs pour savoir si le n est un entier parfait (fonction qui suivra) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if somme k = n then print_string " Le nombre " print_int n print_string "est parfait " else print_string  " Le nombre " print_int n print_string "n'est pas parfait ";;
    Donc voila !
    Alors je ne trouve pas la solution de la récursivité autrement.

    Donc en utilisant la fonction comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let rec somme n =
      if n = 1
      then 0 else if n mod n - 1 =0
      then (n-1) + somme (n-2);;
    ça me renvoie la même erreure !

  4. #4
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Citation Envoyé par fethi510 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let rec somme n =
      if (n mod n-1 =0) then (n-1) + somme (n-2);
      if n = 1 then 1;;
    Bonjour,

    les erreurs sont légion dans cet extrait de code. Elles sont de deux types : les erreurs algorithmiques, et les erreurs de langage.

    • Tout d'abord, l'algo.
      Ce que tu souhaites faire ne te retourneras jamais la somme des diviseurs d'un nombre. Ton idée est de tester chaque entier inférieur à n, et s'il est un diviseur de n l'ajouter à un accumulateur. Lorsque tu as testé tous les nombres, tu souhaites retourner la somme accumulée jusqu'alors.

      Dans le code ci-dessus, ta valeur de n n'est pas fixe, et en effet n modulo (n-1) retournera toujours 1. Ensuite, si l'entier actuellement testé n'est pas un diviseur de n, alors il faut tout de même faire quelque chose.

      Voici un algo que je te propose :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
       
      fonction somme_diviseurs(n: entier): entier
      variables
         index: entier
         somme: entier
      début
         somme = 0
         pour index allant de 1 à n faire
            si index est un diviseur de n alors
               somme = somme + index
            fin si
         fin pour
         retourner somme
      fin.
      Évidemment, cet algo n'est pas du tout compatible avec la façon fonctionnelle de coder. Il te faut le repenser en utilisant la récursivité.

    • Ensuite, le langage.
      Déjà dit : éviter d'utiliser if/then sans else tant que tu n'auras pas bien compris leur sens (voir ça comme l'opérateur ternaire en C -- :?).
      Aussi, a + f b où f est une fonction (int -> int) est une expression invalide puisque équivalente à (a + f) b.



    Reprends donc ton algo à zéro, écris une première version de ta fonction, et nous t'aiderons (si tu le désires) à la perfectionner.


    Cordialement,
    -- Yankel Scialom

Discussions similaires

  1. Somme des diviseurs propres
    Par Neitsa dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 27/03/2012, 23h58
  2. Fonction de calcul de somme des chiffres d'un entier
    Par sam343 dans le forum Langage
    Réponses: 3
    Dernier message: 07/10/2009, 17h35
  3. Somme des N premiers nombres entiers positifs
    Par jujurochedu42 dans le forum Débuter
    Réponses: 2
    Dernier message: 26/09/2009, 23h58
  4. Réponses: 6
    Dernier message: 01/02/2009, 00h14

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