Реализации алгоритмов/Алгоритм Евклида: различия между версиями
→BASIC: Оптимизации |
Усовершенствования алгоритма для разных языков |
||
Строка 27: | Строка 27: | ||
==[[w:Бейсик|BASIC]]== |
==[[w:Бейсик|BASIC]]== |
||
=== |
===Оригинальный (Dartmouth BASIC)=== |
||
Цикл, вычитание (операция нахождения остатка MOD отсутствовала в этой версии языка): |
Цикл, вычитание (операция нахождения остатка MOD отсутствовала в этой версии языка): |
||
<source lang="basic"> |
<source lang="basic"> |
||
10 |
10 PRINT "Two integer numbers"; |
||
20 PRINT "GCD("; A; ", "; B,") = "; |
20 INPUT A, B |
||
30 PRINT "GCD("; A; ", "; B,") = "; |
|||
40 LET A = ABS(A) |
|||
50 IF B = 0 THEN GOTO 120 |
|||
60 LET B = ABS(B) |
|||
50 IF A >= B THEN LET A = A - B: GOTO 50 |
|||
70 IF A < B THEN GOTO 90 |
|||
80 LET A = A - B: GOTO 70 |
|||
90 IF A = 0 THEN LET A = B: GOTO 120 |
|||
100 LET B = B - A: IF B >= A THEN GOTO 100 |
|||
90 PRINT A |
|||
110 IF B > 0 THEN GOTO 80 |
|||
100 END |
|||
120 PRINT A |
|||
130 END |
|||
</source> |
</source> |
||
===[[w:GW-BASIC|GW-BASIC]] и совместимые диалекты=== |
===[[w:GW-BASIC|GW-BASIC]] и совместимые диалекты=== |
||
Цикл, деление с остатком |
Цикл, деление с остатком: |
||
<source lang="basic"> |
<source lang="basic"> |
||
10 INPUT "Two integer numbers", A%, B% |
10 INPUT "Two integer numbers", A%, B% |
||
20 PRINT "GCD("; A%; ", "; B%; ") = "; |
20 PRINT "GCD("; A%; ", "; B%; ") = "; |
||
30 |
30 WHILE B% <> 0 |
||
40 |
40 A% = A% MOD B% |
||
50 A% = A% |
50 IF A% = 0 THEN A% = B%: B% = 0: ELSE B% = B% MOD A% |
||
60 WEND |
|||
60 IF A% = 0 THEN A% = B%: GOTO 90 |
|||
70 PRINT ABS(A%) |
|||
70 B% = B% MOD A% 'Для вычитания заменить на WHILE B% >= A%: B% = B% - A%: WEND |
|||
80 WEND |
|||
90 PRINT A% |
|||
</source> |
</source> |
||
===[[w:QuickBasic|QuickBasic]] версий < 4.0, [[w:Turbo Basic|Turbo Basic]]=== |
===[[w:QuickBasic|QuickBasic]] версий < 4.0, [[w:Turbo Basic|Turbo Basic]]=== |
||
Цикл, деление с остатком |
Цикл, деление с остатком: |
||
<source lang="basic"> |
<source lang="basic"> |
||
DEF FNGCD%(A%, B%) |
DEF FNGCD%(A%, B%) |
||
DO UNTIL B% = 0 |
|||
B% = ABS(B%) |
|||
DO WHILE B% > 0 |
|||
A% = A% MOD B% |
A% = A% MOD B% |
||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'DO UNTIL A% < B% |
|||
' A% = A% - B% |
|||
'LOOP |
|||
IF A% = 0 THEN |
IF A% = 0 THEN |
||
FNGCD% = B% |
FNGCD% = ABS(B%) |
||
EXIT DEF |
EXIT DEF |
||
END IF |
END IF |
||
B% = B% MOD A% |
B% = B% MOD A% |
||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'DO 'Перед входом в этот цикл 0 < A% < B%, поэтому проверка B% < A% вынесена в постусловие |
|||
' B% = B% - A% |
|||
'LOOP UNTIL B% < A% |
|||
LOOP |
LOOP |
||
FNGCD% = A% |
FNGCD% = ABS(A%) |
||
END DEF |
END DEF |
||
</source> |
</source> |
||
Строка 85: | Строка 76: | ||
В следующих примерах используется тип <code>Long</code> (длинное целое); вместо него можно применять также тип <code>Integer</code> (стандартное целое). |
В следующих примерах используется тип <code>Long</code> (длинное целое); вместо него можно применять также тип <code>Integer</code> (стандартное целое). |
||
Цикл, деление с остатком |
Цикл, деление с остатком: |
||
<source lang="vb"> |
<source lang="vb"> |
||
Function GCD(a As Long, b As Long) As Long |
Function GCD(a As Long, b As Long) As Long |
||
Do Until b = 0 |
|||
a = Abs(a) |
|||
b = Abs(b) |
|||
Do While b > 0 |
|||
a = a Mod b |
a = a Mod b |
||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'Do Until a < b |
|||
' a = a - b |
|||
'Loop |
|||
If a = 0 Then |
If a = 0 Then |
||
GCD = b |
GCD = b |
||
Строка 101: | Строка 86: | ||
End If |
End If |
||
b = b Mod a |
b = b Mod a |
||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'Do 'Перед входом в этот цикл 0 < a < b, поэтому проверка b < a вынесена в постусловие |
|||
' b = b - a |
|||
'Loop Until b < a |
|||
Loop |
Loop |
||
GCD = a |
GCD = a |
||
Строка 113: | Строка 94: | ||
<source lang="vb"> |
<source lang="vb"> |
||
Function GCD(a As Long, b As Long) As Long |
Function GCD(a As Long, b As Long) As Long |
||
If b = 0 Then |
|||
GCD = Abs(a) |
|||
Else |
|||
GCD = GCD(b, a Mod b) |
|||
End If |
|||
End Function |
End Function |
||
</source> |
</source> |
||
===[[w:VB.NET| |
===[[w:VB.NET|Visual Basic .NET]]=== |
||
В следующих примерах используется тип <code>Long</code> (длинное целое); вместо него можно применять любые другие целочисленные типы платформы [[w:NET_Framework|.NET]]. |
В следующих примерах используется тип <code>Long</code> (длинное целое); вместо него можно применять любые другие целочисленные типы платформы [[w:NET_Framework|.NET]]. |
||
Цикл, деление с остатком |
Цикл, деление с остатком: |
||
<source lang="vb"> |
<source lang="vb"> |
||
Function GCD(ByVal a As Long, ByVal b As Long) As Long |
|||
Do Until b = 0 |
|||
a = Math.Abs(a) |
|||
b = Math.Abs(b) |
|||
Do While b > 0 |
|||
a = a Mod b |
a = a Mod b |
||
If a = 0 Then Return Math.Abs(b) |
|||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'Do Until a < b |
|||
' a -= b |
|||
'Loop |
|||
If a = 0 Then Return b |
|||
b = b Mod a |
b = b Mod a |
||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'Do 'Перед входом в этот цикл 0 < a < b, поэтому проверка b < a вынесена в постусловие |
|||
' b -= a |
|||
'Loop Until b < a |
|||
Loop |
Loop |
||
Return a |
Return Math.Abs(a) |
||
End Function |
End Function |
||
</source> |
</source> |
||
Рекурсия, деление с остатком |
Рекурсия, деление с остатком: |
||
<source lang="vb"> |
<source lang="vb"> |
||
Function GCD(ByVal a As Long, ByVal b As Long) As Long |
|||
Return If(b = 0, Math.Abs(a), GCD(b, a Mod b)) ' VB.NET 2008 или более поздняя версия |
|||
If b = 0 Then Return Math.Abs(a) |
|||
Return GCD(b, a Mod b) |
|||
'Для вычитания убрать предыдущую строку и раскомментировать следующие: |
|||
'If a >= b Then Return GCD(a, a - b) |
|||
'Return GCD(b, b - a) |
|||
End Function |
End Function |
||
</source> |
</source> |
||
==[[w:C (язык программирования)|C]]/[[w:C++|C++]]== |
==[[w:C (язык программирования)|C]]/[[w:C++|C++]]== |
||
'''C:''' Тип <code> |
'''C:''' Тип <code>Integer</code> должен быть задан как: |
||
<source lang="c">typedef int |
<source lang="c">typedef int Integer; /* Вместо int можно подставить любой другой целочисленный тип */</source> |
||
'''C++:''' Любую из нижеприведённых функций (включая <code>abs</code>) следует предварить строкой: |
'''C++:''' Любую из нижеприведённых функций (включая <code>abs</code>) следует предварить строкой: |
||
<source lang="cpp">template < |
<source lang="cpp">template <typename Integer></source> |
||
Для корректной обработки отрицательных чисел все последующие примеры на C/C++ используют функцию вычисления модуля числа: |
Для корректной обработки отрицательных чисел все последующие примеры на C/C++ используют функцию вычисления модуля числа: |
||
<source lang="c"> |
<source lang="c"> |
||
Integer abs (Integer value) { |
|||
return (value < 0) ? -value : value; |
|||
} |
} |
||
</source> |
</source> |
||
Деление с остатком, цикл: |
Деление с остатком, цикл: |
||
<source lang="c"> |
<source lang="c"> |
||
Integer gcd (Integer a, Integer b) { |
|||
for (Integer c; b; ) { |
|||
IntType c; |
|||
c = a % b; |
|||
a = b; |
|||
b = c; |
|||
} |
|||
b = c; |
|||
return abs(a); |
|||
} |
|||
} |
|||
return abs(a); |
|||
</source> |
|||
Без использования дополнительной переменной: |
|||
<source lang="c"> |
|||
Integer gcd (Integer a, Integer b) { |
|||
while (b) |
|||
b ^= a ^= b ^= a %= b; |
|||
return abs(a); |
|||
} |
} |
||
</source> |
</source> |
||
Без использования дополнительной переменной и с наименьшим числом сравнений и присваиваний: |
|||
Более короткое решение: |
|||
<source lang="c"> |
<source lang="c"> |
||
Integer gcd (Integer a, Integer b) { |
|||
if (!a) |
|||
return abs(b); |
|||
b ^= a ^= b ^= a %= b; |
|||
if (!b) |
|||
return abs(a); |
|||
for ( ; ; ) |
|||
if (!(a %= b)) |
|||
return abs(b); |
|||
else if (!(b %= a)) |
|||
return abs(a); |
|||
} |
} |
||
</source> |
</source> |
||
Строка 194: | Строка 176: | ||
Деление с остатком, рекурсия: |
Деление с остатком, рекурсия: |
||
<source lang="c"> |
<source lang="c"> |
||
Integer gcd (Integer a, Integer b) { |
|||
return !b ? abs(a) : gcd(b, a % b); |
|||
} |
} |
||
</source> |
</source> |
||
Строка 201: | Строка 183: | ||
Вычитание, цикл: |
Вычитание, цикл: |
||
<source lang="c"> |
<source lang="c"> |
||
Integer gcd (Integer a, Integer b) { |
|||
a = abs(a); |
|||
b = abs(b); |
|||
while (b) { |
|||
while (a >= b) |
|||
a -= b; |
|||
if (!a) |
|||
else |
|||
return b; |
|||
b -= a; |
|||
do { |
|||
b -= a; |
|||
} while (b >= a); |
|||
} |
} |
||
return a; |
return a; |
||
Строка 214: | Строка 199: | ||
</source> |
</source> |
||
==[[w:C_Sharp|C#]], [[w:Java|Java]]== |
|||
==[[w:C_Sharp|C#]], [[w:Java|Java]]<ref>Для соответствия правилам оформления кода Java метод следует переименовать в <code>gcd</code> и перенести <code>{</code> в конец предыдущей строки</ref>== |
|||
Приведён код для C#. Для Java следует заменить <code>Abs</code> на <code>abs</code> и, для соответствия правилам оформления кода, переименовать функции в <code>gcd</code> и перенести <code>{</code> в конец предыдущей строки. |
|||
Вместо <code>long</code> можно использовать и другие целочисленные типы — <code>byte</code>, <code>int</code> и т. д. |
Вместо <code>long</code> можно использовать и другие целочисленные типы — <code>byte</code>, <code>int</code> и т. д. |
||
Деление с остатком, цикл: |
Деление с остатком, цикл: |
||
<source lang="csharp"> |
<source lang="csharp"> |
||
static long GCD |
static long GCD(long a, long b) |
||
{ |
{ |
||
while (b != 0) |
while (b != 0) |
||
b = a % (a = b); |
b = a % (a = b); |
||
return a |
return Math.Abs(a); |
||
} |
|||
</source> |
|||
<source lang="csharp"> |
|||
static long GCD(long a, long b) |
|||
{ |
|||
if (a == 0) |
|||
return Math.Abs(b); |
|||
if (b == 0) |
|||
return Math.Abs(a); |
|||
for ( ; ; ) { |
|||
if ((a %= b) == 0) |
|||
return Math.Abs(b); |
|||
if ((b %= a) == 0) |
|||
return Math.Abs(a); |
|||
} |
|||
} |
} |
||
</source> |
</source> |
||
Строка 231: | Строка 234: | ||
static long GCD (long a, long b) |
static long GCD (long a, long b) |
||
{ |
{ |
||
return b == 0 ? ( |
return b == 0 ? Math.Abs(a) : GCD(b, a % b); |
||
} |
} |
||
</source> |
</source> |
||
Строка 260: | Строка 263: | ||
Тип <code>IntType</code> определён как: |
Тип <code>IntType</code> определён как: |
||
<source lang="go"> |
<source lang="go"> |
||
type |
type Integer = int // Вместо int можно подставить любой другой целочисленный тип |
||
</source> |
</source> |
||
Для корректной обработки отрицательных чисел все последующие примеры на Go используют функцию вычисления модуля числа: |
Для корректной обработки отрицательных чисел все последующие примеры на Go используют функцию вычисления модуля числа: |
||
<source lang="go"> |
<source lang="go"> |
||
func IntAbs(value |
func IntAbs(value Integer) Integer { |
||
if value < 0 { |
if value < 0 { |
||
return -value |
return -value |
||
Строка 275: | Строка 278: | ||
Деление с остатком, цикл: |
Деление с остатком, цикл: |
||
<source lang="go"> |
<source lang="go"> |
||
func GCD(a, b |
func GCD(a, b Integer) Integer { |
||
for b != 0 { |
for b != 0 { |
||
a %= b |
a %= b |
||
Строка 287: | Строка 290: | ||
</source> |
</source> |
||
Деление с остатком, рекурсия: |
|||
Вычитание, цикл: |
|||
<source lang="go"> |
<source lang="go"> |
||
func GCD(a, b |
func GCD(a, b Integer) Integer { |
||
if b == 0 { |
|||
a = IntAbs(a) |
|||
return IntAbs(a) |
|||
for b != 0 { |
|||
for a >= b { |
|||
a -= b |
|||
} |
|||
if a == 0 { |
|||
return b |
|||
} |
|||
for b >= a { |
|||
b -= a |
|||
} |
|||
} |
} |
||
return a |
return GCD(b, a % b) |
||
} |
} |
||
</source> |
</source> |
||
Строка 318: | Строка 311: | ||
==[[w:Паскаль (язык программирования)|Pascal]]== |
==[[w:Паскаль (язык программирования)|Pascal]]== |
||
Тип <code> |
Тип <code>TInteger</code> определён как: |
||
<source lang="pascal"> |
<source lang="pascal"> |
||
type |
type TInteger = Integer; { Вместо Integer можно подставить любой другой целочисленный тип } |
||
</source> |
</source> |
||
Деление с остатком, цикл: |
Деление с остатком, цикл: |
||
<source lang="pascal"> |
<source lang="pascal"> |
||
function GCD |
function GCD(a, b: TInteger): TInteger; |
||
begin |
|||
while a * b <> 0 do |
|||
if a > b then |
|||
a := a mod b |
|||
else |
|||
b := b mod a; |
|||
GCD := Abs(a + b) |
|||
end; |
|||
</source> |
|||
Более быстрый алгоритм: |
|||
<source lang="pascal"> |
|||
function GCD (a, b: IntType): IntType; |
|||
var c: IntType; |
|||
begin |
begin |
||
while b <> 0 do |
|||
begin |
|||
a := a mod b; |
|||
if a = 0 then |
|||
begin |
|||
b := c |
|||
a := b; |
|||
b := 0 |
|||
end |
|||
else |
|||
b := b mod a |
|||
end; |
|||
GCD := Abs(a) |
|||
end; |
end; |
||
</source> |
</source> |
||
Строка 353: | Строка 337: | ||
Деление с остатком, рекурсия: |
Деление с остатком, рекурсия: |
||
<source lang="pascal"> |
<source lang="pascal"> |
||
function GCD |
function GCD(a, b: TInteger): TInteger; |
||
begin |
begin |
||
if b = 0 then |
|||
GCD := Abs(a) |
|||
else |
|||
GCD := GCD(b, a mod b) |
|||
end; |
end; |
||
</source> |
</source> |
||
Строка 366: | Строка 350: | ||
<source lang="perl"> |
<source lang="perl"> |
||
sub gcd { |
sub gcd { |
||
return $_[0] != 0 ? gcd ( ( $_[1] % $_[0] ), $_[0] ) : $_[1]; |
|||
} |
} |
||
</source> |
</source> |
||
Строка 374: | Строка 358: | ||
<source lang="php"> |
<source lang="php"> |
||
function gcd ($a, $b) { |
function gcd ($a, $b) { |
||
if ($a === 0) |
|||
return abs($b); |
|||
if ($a > $b) |
|||
if ($b === 0) |
|||
$a = $a % $b; |
|||
return abs($a) |
|||
else |
|||
for ( ; ; ) |
|||
$b = $b % $a; |
|||
if (($a %= $b) === 0) |
|||
} |
|||
return abs($b); |
|||
else if (($b %= $a) === 0) |
|||
return abs($a); |
|||
} |
} |
||
echo gcd(5, 3); |
echo gcd(5, 3); |
||
Строка 409: | Строка 395: | ||
Деление с остатком, цикл: |
Деление с остатком, цикл: |
||
<source lang="python"> |
<source lang="python"> |
||
def gcd |
def gcd(a: int, b: int) -> int: |
||
while b: |
|||
a, b = b, a % b |
|||
return abs(a) |
|||
</source> |
</source> |
||
Деление с остатком, рекурсия: |
Деление с остатком, рекурсия: |
||
<source lang="python"> |
<source lang="python"> |
||
def gcd |
def gcd(a: int, b: int) -> int: |
||
return abs(a) if b == 0 else gcd(b, a % b) |
|||
</source> |
</source> |
||
Строка 424: | Строка 410: | ||
Деление с остатком, цикл: |
Деление с остатком, цикл: |
||
<source lang="ruby"> |
<source lang="ruby"> |
||
def gcd |
def gcd(a, b) |
||
a, b = b, a % b until b.zero? |
|||
a.abs |
|||
end |
end |
||
</source> |
</source> |
||
Строка 432: | Строка 418: | ||
Деление с остатком, рекурсия: |
Деление с остатком, рекурсия: |
||
<source lang="ruby"> |
<source lang="ruby"> |
||
def gcd |
def gcd(a, b) |
||
return a.abs if b.zero? |
|||
gcd(b, a % b) |
|||
end |
|||
</source> |
|||
Вычитание, цикл: |
|||
<source lang="ruby"> |
|||
def gcd (a, b) |
|||
a = a.abs |
|||
b = b.abs |
|||
if a > b |
|||
a -= b |
|||
else |
|||
b -= a |
|||
end while a != b |
|||
a |
|||
end |
end |
||
</source> |
</source> |
||
Строка 463: | Строка 435: | ||
pub fn gcd <IntType> (mut a: IntType, mut b: IntType) -> IntType |
pub fn gcd <IntType> (mut a: IntType, mut b: IntType) -> IntType |
||
where IntType: Copy + FromPrimitive + PartialEq + Rem<Output = IntType> { |
where IntType: Copy + FromPrimitive + PartialEq + Rem<Output = IntType> { |
||
let zero = FromPrimitive::from_u32(0u32).unwrap(); // Обобщённая константа 0 |
|||
let mut c: IntType; |
|||
while b != zero { |
|||
c = a % b; |
|||
a = b; |
|||
b = c; |
|||
} |
|||
} |
|||
a |
|||
a |
|||
} |
} |
||
</source> |
</source> |
||
Строка 480: | Строка 452: | ||
pub fn gcd <T: Copy + PartialOrd + SubAssign> (mut a: T, mut b: T) -> T { |
pub fn gcd <T: Copy + PartialOrd + SubAssign> (mut a: T, mut b: T) -> T { |
||
while a != b { |
|||
if a > b { |
|||
a -= b; |
|||
} else { |
|||
b -= a; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
a |
|||
a |
|||
} |
} |
||
</source> |
</source> |
||
Строка 502: | Строка 474: | ||
<source lang="bash"> |
<source lang="bash"> |
||
gcd () { |
gcd () { |
||
n = 1 a = $1 b = $2 |
|||
if [[ $a -ne 0 ]] |
|||
then |
|||
gcd $(( $b % $a )) $a |
|||
let "n = $?" |
|||
else |
|||
let "n = $b" |
|||
fi |
|||
return $n |
|||
} |
} |
||
Строка 522: | Строка 494: | ||
ЗАДАЧА НОД (a, b: ЦЕЛ): ЦЕЛ; |
ЗАДАЧА НОД (a, b: ЦЕЛ): ЦЕЛ; |
||
УКАЗ |
УКАЗ |
||
ПОКА b # 0 ВЫП |
|||
a := a ОСТАТОК b; |
|||
ЕСЛИ a < b ТО |
|||
ЕСЛИ a = 0 ТО |
|||
b := b ОСТАТОК a |
|||
a := b; |
|||
b := 0 |
|||
a := a ОСТАТОК b |
|||
ИНАЧЕ |
|||
b := b ОСТАТОК a |
|||
КОН |
КОН |
||
КОН; |
КОН; |
||
ВОЗВРАТ МОДУЛЬ(a |
ВОЗВРАТ МОДУЛЬ(a) |
||
КОН НОД; |
КОН НОД; |
||
</source> |
</source> |
Версия от 06:29, 3 августа 2019
Реализации алгоритма Евклида для вычисления НОД — наибольшего общего делителя (англ. GCD — greatest common divisor) двух целых чисел на различных языках программирования.
Реализации
Assembler
ARM
Вычитание, цикл:
loop CMP Ri, Rj ; проверка условий NE (i != j), GT (i > j) и LT (i < j);
SUBGT Ri, Ri, Rj ; если GT, выполняется i = i-j;
SUBLT Rj, Rj, Ri ; если LT, выполняется j = j-i;
BNE loop ; если NE - переход на метку loop.
Z80
Вычитание, цикл:
GCD_DEHL: ; CALL Inputs: HL,DE; Output: DE
AND A ; сброс CF
LOOP:
SBC HL,DE ; совмещение трёх в одном - одного сравнения и поочередно двух вычитаний.
RET Z ; минимизация общего размера, поэтому в цикле.
JR NC,LOOP
ADD HL,DE ; откат лишнего вычитания
EX DE,HL
JR GCD_DEHL
BASIC
Оригинальный (Dartmouth BASIC)
Цикл, вычитание (операция нахождения остатка MOD отсутствовала в этой версии языка):
10 PRINT "Two integer numbers";
20 INPUT A, B
30 PRINT "GCD("; A; ", "; B,") = ";
40 LET A = ABS(A)
50 IF B = 0 THEN GOTO 120
60 LET B = ABS(B)
70 IF A < B THEN GOTO 90
80 LET A = A - B: GOTO 70
90 IF A = 0 THEN LET A = B: GOTO 120
100 LET B = B - A: IF B >= A THEN GOTO 100
110 IF B > 0 THEN GOTO 80
120 PRINT A
130 END
GW-BASIC и совместимые диалекты
Цикл, деление с остатком:
10 INPUT "Two integer numbers", A%, B%
20 PRINT "GCD("; A%; ", "; B%; ") = ";
30 WHILE B% <> 0
40 A% = A% MOD B%
50 IF A% = 0 THEN A% = B%: B% = 0: ELSE B% = B% MOD A%
60 WEND
70 PRINT ABS(A%)
QuickBasic версий < 4.0, Turbo Basic
Цикл, деление с остатком:
DEF FNGCD%(A%, B%)
DO UNTIL B% = 0
A% = A% MOD B%
IF A% = 0 THEN
FNGCD% = ABS(B%)
EXIT DEF
END IF
B% = B% MOD A%
LOOP
FNGCD% = ABS(A%)
END DEF
PowerBASIC, QBASIC, QuickBasic версий ≥ 4.0, Visual Basic
В следующих примерах используется тип Long
(длинное целое); вместо него можно применять также тип Integer
(стандартное целое).
Цикл, деление с остатком:
Function GCD(a As Long, b As Long) As Long
Do Until b = 0
a = a Mod b
If a = 0 Then
GCD = b
Exit Function
End If
b = b Mod a
Loop
GCD = a
End Function
Рекурсия, деление с остатком:
Function GCD(a As Long, b As Long) As Long
If b = 0 Then
GCD = Abs(a)
Else
GCD = GCD(b, a Mod b)
End If
End Function
Visual Basic .NET
В следующих примерах используется тип Long
(длинное целое); вместо него можно применять любые другие целочисленные типы платформы .NET.
Цикл, деление с остатком:
Function GCD(ByVal a As Long, ByVal b As Long) As Long
Do Until b = 0
a = a Mod b
If a = 0 Then Return Math.Abs(b)
b = b Mod a
Loop
Return Math.Abs(a)
End Function
Рекурсия, деление с остатком:
Function GCD(ByVal a As Long, ByVal b As Long) As Long
Return If(b = 0, Math.Abs(a), GCD(b, a Mod b)) ' VB.NET 2008 или более поздняя версия
End Function
C/C++
C: Тип Integer
должен быть задан как:
typedef int Integer; /* Вместо int можно подставить любой другой целочисленный тип */
C++: Любую из нижеприведённых функций (включая abs
) следует предварить строкой:
template <typename Integer>
Для корректной обработки отрицательных чисел все последующие примеры на C/C++ используют функцию вычисления модуля числа:
Integer abs (Integer value) {
return (value < 0) ? -value : value;
}
Деление с остатком, цикл:
Integer gcd (Integer a, Integer b) {
for (Integer c; b; ) {
c = a % b;
a = b;
b = c;
}
return abs(a);
}
Без использования дополнительной переменной:
Integer gcd (Integer a, Integer b) {
while (b)
b ^= a ^= b ^= a %= b;
return abs(a);
}
Без использования дополнительной переменной и с наименьшим числом сравнений и присваиваний:
Integer gcd (Integer a, Integer b) {
if (!a)
return abs(b);
if (!b)
return abs(a);
for ( ; ; )
if (!(a %= b))
return abs(b);
else if (!(b %= a))
return abs(a);
}
Деление с остатком, рекурсия:
Integer gcd (Integer a, Integer b) {
return !b ? abs(a) : gcd(b, a % b);
}
Вычитание, цикл:
Integer gcd (Integer a, Integer b) {
a = abs(a);
b = abs(b);
while (b) {
while (a >= b)
a -= b;
if (!a)
return b;
do {
b -= a;
} while (b >= a);
}
return a;
}
C#, Java
Приведён код для C#. Для Java следует заменить Abs
на abs
и, для соответствия правилам оформления кода, переименовать функции в gcd
и перенести {
в конец предыдущей строки.
Вместо long
можно использовать и другие целочисленные типы — byte
, int
и т. д.
Деление с остатком, цикл:
static long GCD(long a, long b)
{
while (b != 0)
b = a % (a = b);
return Math.Abs(a);
}
static long GCD(long a, long b)
{
if (a == 0)
return Math.Abs(b);
if (b == 0)
return Math.Abs(a);
for ( ; ; ) {
if ((a %= b) == 0)
return Math.Abs(b);
if ((b %= a) == 0)
return Math.Abs(a);
}
}
Деление с остатком, рекурсия:
static long GCD (long a, long b)
{
return b == 0 ? Math.Abs(a) : GCD(b, a % b);
}
Erlang
Деление с остатком, рекурсия:
gcd(A, 0) -> A;
gcd(A, B) -> gcd(B, (A rem B)).
F#
Деление с остатком, рекурсия:
let rec gcd a b =
match b with
|0 -> a
|b -> gcd b (a % b)
Forth (диалект RetroForth)
Деление с остатком, рекурсия:
: GCD ( n1 n2 -- n ) tuck mod 0; GCD ;
Go
Тип IntType
определён как:
type Integer = int // Вместо int можно подставить любой другой целочисленный тип
Для корректной обработки отрицательных чисел все последующие примеры на Go используют функцию вычисления модуля числа:
func IntAbs(value Integer) Integer {
if value < 0 {
return -value
}
return value
}
Деление с остатком, цикл:
func GCD(a, b Integer) Integer {
for b != 0 {
a %= b
if a == 0 {
return IntAbs(b)
}
b %= a
}
return IntAbs(a)
}
Деление с остатком, рекурсия:
func GCD(a, b Integer) Integer {
if b == 0 {
return IntAbs(a)
}
return GCD(b, a % b)
}
Haskell
Деление с остатком, рекурсия:
gcd :: Integral a => a -> a -> a
gcd 0 0 = error "НОД от 0 и 0 не определён."
gcd x y = gcd' (abs x) (abs y)
where gcd' x 0 = x
gcd' x y = gcd' y (x `rem` y)
Pascal
Тип TInteger
определён как:
type TInteger = Integer; { Вместо Integer можно подставить любой другой целочисленный тип }
Деление с остатком, цикл:
function GCD(a, b: TInteger): TInteger;
begin
while b <> 0 do
begin
a := a mod b;
if a = 0 then
begin
a := b;
b := 0
end
else
b := b mod a
end;
GCD := Abs(a)
end;
Деление с остатком, рекурсия:
function GCD(a, b: TInteger): TInteger;
begin
if b = 0 then
GCD := Abs(a)
else
GCD := GCD(b, a mod b)
end;
Perl
Деление с остатком, рекурсия:
sub gcd {
return $_[0] != 0 ? gcd ( ( $_[1] % $_[0] ), $_[0] ) : $_[1];
}
PHP
Деление с остатком, цикл:
function gcd ($a, $b) {
if ($a === 0)
return abs($b);
if ($b === 0)
return abs($a)
for ( ; ; )
if (($a %= $b) === 0)
return abs($b);
else if (($b %= $a) === 0)
return abs($a);
}
echo gcd(5, 3);
Prolog
Деление с остатком, рекурсия:
?GCD(a, b, x)
GCD(0, b, b) <-
GCD(a, 0, a) <-
GCD(a, b, x) <- a >= b, m is a mod b, GCD(m, b, x)
GCD(a, b, x) <- a < b, m is b mod a, GCD(a, m, x)
w:SWI-Prolog
Деление с остатком, рекурсия:
gcd(0, B, B).
gcd(A, 0, A).
gcd(A, B, X) :- A >= B, M is A mod B, gcd(M, B, X).
gcd(A, B, X) :- A < B, M is B mod A, gcd(A, M, X).
Python
Деление с остатком, цикл:
def gcd(a: int, b: int) -> int:
while b:
a, b = b, a % b
return abs(a)
Деление с остатком, рекурсия:
def gcd(a: int, b: int) -> int:
return abs(a) if b == 0 else gcd(b, a % b)
Ruby
Деление с остатком, цикл:
def gcd(a, b)
a, b = b, a % b until b.zero?
a.abs
end
Деление с остатком, рекурсия:
def gcd(a, b)
return a.abs if b.zero?
gcd(b, a % b)
end
Rust
Деление с остатком, цикл:
extern crate num;
use self::num::FromPrimitive;
use std::ops::Rem;
pub fn gcd <IntType> (mut a: IntType, mut b: IntType) -> IntType
where IntType: Copy + FromPrimitive + PartialEq + Rem<Output = IntType> {
let zero = FromPrimitive::from_u32(0u32).unwrap(); // Обобщённая константа 0
let mut c: IntType;
while b != zero {
c = a % b;
a = b;
b = c;
}
a
}
Вычитание, цикл:
use std::ops::SubAssign;
pub fn gcd <T: Copy + PartialOrd + SubAssign> (mut a: T, mut b: T) -> T {
while a != b {
if a > b {
a -= b;
} else {
b -= a;
}
}
a
}
Scheme
Вычитание, рекурсия:
(define gcd (lambda (a b) (if (> a b) (gcd (- a b) b) (if (< a b) (gcd a (- b a)) a))))
Shell
Деление с остатком, рекурсия:
gcd () {
n = 1 a = $1 b = $2
if [[ $a -ne 0 ]]
then
gcd $(( $b % $a )) $a
let "n = $?"
else
let "n = $b"
fi
return $n
}
gcd $1 $2
echo "Greatest common divisor is $?"
Глагол
Деление с остатком, цикл:
ЗАДАЧА НОД (a, b: ЦЕЛ): ЦЕЛ;
УКАЗ
ПОКА b # 0 ВЫП
a := a ОСТАТОК b;
ЕСЛИ a = 0 ТО
a := b;
b := 0
ИНАЧЕ
b := b ОСТАТОК a
КОН
КОН;
ВОЗВРАТ МОДУЛЬ(a)
КОН НОД;
Программируемые микрокалькуляторы «Электроника»
Использование: <первое число> В↑ <второе число> В/О С/П (НОД на индикаторе).
МК-61 / 52 / 152 / 161 / 163 / 1152
Деление с остатком, цикл. Корректно обрабатываются любые целые числа (включая 0 и отрицательные). В вычислениях участвуют только регистры стека.
00. Fx≠0 01. 13 02. ↔ 03. В↑ 04. FВx 05. ÷ 06. FВx 07. ↔ 08. K[x] 09. ×
10. − 11. Fx=0 12. 02 13. + 14. K|x| 15. С/П
Б3-34, МК-54 / 56 / 61 / 52 / 152 / 161 / 163 / 1152
Вычитание, цикл. Корректно обрабатываются любые целые неотрицательные числа. В вычислениях участвуют только регистры стека X и Y.
00. − 01. Fx≠0 02. 12 03. Fx<0 04. 09 05. FВx 06. ↔ 07. /−/ 08. − 09. FВx
10. БП 11. 00 12. FВx 13. С/П
Б3-21, МК-46 / 64, МС-1103
Вычитание, цикл. Корректно обрабатываются любые целые неотрицательные числа. В вычислениях участвуют только регистры стека X и Y.
00. Px≠0 01. ↔ 02. − 03. Px≥0 04. F1 05. ↔
10. − 11. /−/ 12. ↔ 13. Px=0 14. Peⁱˣ 15. ↔
20. С/П