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
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:
- nous produisons une séquence avec
Sequence{a..b}
- cette séquence est passe de
1
au nombre plus élevé entrex
ety
(if x < y then Sequence{1..y} else Sequence{1..x}
) - cette séquence est stockée dans un immuable variable
divs
(let divs : Sequence(Integer) = ... in ...
) - de
divs
, nous sélectionnons seulement le nombrez
qui est un diviseur pourx
etz
(divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)
- 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()
Est-il un soutien dans la norme OCL? quel est l'ensemble à produire ou à retourner? – any
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? –
Bytheway, vous pouvez réduire l'expression (voir mon édition), et tout est toujours standard OCL. –