2016-06-16 3 views
0

Comment écrire une opération gcd(x : Integer, y : Integer) : Integer qui renvoie le plus grand commun diviseur de deux entiers positifs (le plus grand entier qui les divise exactement) en ocl?le plus grand commun diviseur en ocl

Répondre

0

Voici une solution simple pour cela (certainement pas efficace, mais il fonctionne):

let divs : Sequence(Integer) = if x < y then Sequence{1..y} else Sequence{1..x} endif 
in divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last() 

Ce qui est tout simplement fait est qu'une séquence de chaque candidat de potentiels est généré, puis, à partir de cette séquence, seule ceux qui se divisent x et y sont sélectionnés et stockés dans une nouvelle séquence (qui est commandée). Enfin, le dernier numéro de cette séquence filtrée est votre plus grand commun diviseur.

maintenant dans les détails:

  1. nous produisons une séquence avec Sequence{a..b}
  2. cette séquence est passe de 1 au nombre plus élevé entre x et y (if x < y then Sequence{1..y} else Sequence{1..x})
  3. cette séquence est stockée dans un immuable variable divs (let divs : Sequence(Integer) = ... in ...)
  4. de divs, nous sélectionnons seulement le nombre z qui est un diviseur pour x et z (divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)
  5. enfin, nous prenons seulement le dernier élément de la nouvelle séquence (select(...)->last())

Si la fonction last() n'existe pas dans votre env (ne savent pas pourquoi, mais certaines implémentations OCL apporter leurs propres fonctions), vous pouvez utiliser:

->sortedBy(i | -i)->at(1) 

au lieu de last(), qui inverse la séquence et prendre le premier élément.

EDIT>

Vous pouvez également réduire l'expression de cette façon:

let divs : Sequence(Integer) = Sequence{1..x.max(y)} 
in divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last() 

ou, en supprimant l'utilisation de divs

Sequence{1..x.max(y)}->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last() 
+0

Est-il un soutien dans la norme OCL? quel est l'ensemble à produire ou à retourner? – any

+0

J'ai vérifié, 'last()' est OCL standard (spécification, p.170). C'était le seul point dont je n'étais pas sûr. Tout le reste est évidemment standard. Cette expression ne fonctionne pas pour vous? –

+0

Bytheway, vous pouvez réduire l'expression (voir mon édition), et tout est toujours standard OCL. –