ocl中的最大公约数

greatest common divisor in ocl

如何写一个操作gcd(x : Integer, y : Integer) : Integer returns ocl 中两个正整数的最大公约数(能整除它们的最大整数)?

这里有一个简单的解决方案(当然无效,但有效):

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 相除的 selected 和存储在一个新序列中(已排序)。最后,此过滤序列的最后一个数字是您的最大公约数。

现在详细介绍:

  1. 我们用 Sequence{a..b}
  2. 生成一个序列
  3. 这个序列是从 1xy 之间的较大数字 (if x < y then Sequence{1..y} else Sequence{1..x})
  4. 这个序列存储在一个不可变变量中divs (let divs : Sequence(Integer) = ... in ...)
  5. divs,我们select只有数字z,它是xz的约数(divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)
  6. 最后,我们只取新序列的最后一个元素 (select(...)->last())

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