Précédent   Forum du club des développeurs et IT Pro > Autres langages > Langages fonctionnels > Caml
Caml Forum d'entraide sur la programmation avec les langages fonctionnels Caml-Light et OCaml
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 01/06/2012, 13h17   #1
fethi510
Invité de passage
 
Homme
Étudiant
Inscription : janvier 2012
Messages : 2
Détails du profil
Informations personnelles :
Sexe : Homme

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2012
Messages : 2
Points : 0
Points : 0
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 :
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 :
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
fethi510 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2012, 13h41   #2
Ptival
Membre actif
 
Avatar de Ptival
 
Homme Valentin Robert
Étudiant
Inscription : juin 2004
Messages : 70
Détails du profil
Informations personnelles :
Nom : Homme Valentin Robert
Âge : 24
Localisation : Etats-Unis

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2004
Messages : 70
Points : 172
Points : 172
Quant à la réponse :
est un sucre syntaxique pour :
Code :
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 :
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 :
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 :
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.
Ptival est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2012, 13h57   #3
fethi510
Invité de passage
 
Homme
Étudiant
Inscription : janvier 2012
Messages : 2
Détails du profil
Informations personnelles :
Sexe : Homme

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2012
Messages : 2
Points : 0
Points : 0
Citation:
Envoyé par Ptival Voir le message
Quant à la réponse :
est un sucre syntaxique pour :
Code :
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 :
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 :
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 :
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 :
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 :
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 !
fethi510 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/06/2012, 14h42   #4
prgasp77
Membre Expert
 
Avatar de prgasp77
 
Homme Yankel Scialom
Ingénieur en systèmes embarqués
Inscription : juin 2004
Messages : 999
Détails du profil
Informations personnelles :
Nom : Homme Yankel Scialom
Âge : 26
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 : 999
Points : 1 419
Points : 1 419
Citation:
Envoyé par fethi510 Voir le message
Code :
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 :
    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,
__________________
gasp in touch
-- Yankel Scialom
prgasp77 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 19h34.


 
 
 
 
Partenaires

Hébergement Web