0

gcd(x : Integer, y : Integer) : Integer2 つの正の整数 (両方を正確に割る最大の整数) の最大公約数を返す演算を でどのように記述できoclますか?

4

1 に答える 1

0

これに対する簡単な解決策を次に示します (確かに効果的ではありませんが、機能します)。

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()

簡単に言えば、各ポテンシャル候補のシーケンスが生成され、このシーケンスから、分割されたもののみxy選択され、新しいシーケンスに格納されます (順序付けられます)。最後に、このフィルター処理されたシーケンスの最後の数値が最大公約数です。

詳細は次のとおりです。

  1. でシーケンスを生成しますSequence{a..b}
  2. このシーケンスは からと( )1の間の大きい方の番号になります。xyif x < y then Sequence{1..y} else Sequence{1..x}
  3. このシーケンスは、不変変数divs( let divs : Sequence(Integer) = ... in ...)に格納されます。
  4. からと( divs_ z_xzdivs->select(z | x.mod(z) = 0 and y.mod(z) = 0)
  5. 最後に、新しいシーケンスから最後の要素のみを取得します ( select(...)->last())

関数がenvに存在しない場合last()(理由はわかりませんが、一部のOCL実装では独自の関数が導入されています)、次を使用できます。

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

の代わりにlast()、シーケンスを逆にして最初の要素を取ります。

編集>

この方法で式を減らすこともできます。

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

または、の使用を削除することによってdivs

Sequence{1..x.max(y)}->select(z | x.mod(z) = 0 and y.mod(z) = 0)->last()
于 2016-06-17T06:38:51.880 に答える