2016-06-16 3 views
0

Как написать операцию gcd(x : Integer, y : Integer) : Integer, которая возвращает наибольший общий делитель из двух натуральных чисел (наибольшее целое число, которое их разделяет точно) в ocl?наибольший общий делитель в ocl

ответ

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

Что просто сделать то, что последовательность каждого кандидатов потенциалов генерируется, то из этой последовательности, только те, которые делят x и y, выбираются и сохраняются в новой последовательности (которая упорядочена). Наконец, последнее число из этой отфильтрованной последовательности - ваш наибольший общий делитель.

Теперь в деталях:

  1. мы производим последовательность с Sequence{a..b}
  2. эта последовательность переходит из 1 к большему числу между x и y (if x < y then Sequence{1..y} else Sequence{1..x})
  3. эта последовательность хранится в неизменны переменная divs (let divs : Sequence(Integer) = ... in ...)
  4. от divs, мы выбираем только номер z, который является делителем для x и z (divs->select(z | x.mod(z) = 0 and y.mod(z) = 0)
  5. наконец, мы только взять последний элемент из новой последовательности (select(...)->last())

Если функция last() не существует в вашем окр (не знаю, почему, но некоторые OCL реализации приносят свои собственные функции), вы можете использовать:

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

вместо last(), которые в обратном порядке и принять первый элемент.

EDIT>

Вы также можете привести выражение таким образом:

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

ли это поддержка в стандартном OCL? каков набор результатов или возврата? – any

+0

Я проверил, 'last()' является стандартным OCL (спецификация, стр.170). Это был единственный момент, о котором я не знал. Все остальное очевидно стандартно. Это выражение не работает для вас? –

+0

Bytheway, вы можете уменьшить выражение (см. Мое редактирование), и все по-прежнему является стандартным OCL. –

Смежные вопросы