Skip to content

Commit 4006710

Browse files
authored
Merge pull request #104 from PatrykOlejniczak/fix-greatest-common-divisor
Fix unit test, separate version GCD algorithm to stein and euclidean.
2 parents d1ca661 + 980a1d3 commit 4006710

File tree

3 files changed

+138
-97
lines changed

3 files changed

+138
-97
lines changed
Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,73 @@
1-
/***
2-
* Euclidean Algorithm to find the greatest common divisor of two numbers.
3-
*
4-
*/
5-
1+
using System;
62

73
namespace Algorithms.Numeric
84
{
95
public static class GreatestCommonDivisor
106
{
117
/// <summary>
12-
/// Finds and returns the greatest common divisor of two numbers
8+
/// Returns the greatest common divisor of two numbers using Euclidean Algorithm.
139
/// </summary>
14-
public static uint FindGCD(uint a, uint b)
10+
public static int FindGCDEuclidean(int a, int b)
1511
{
12+
a = Math.Abs(a);
13+
b = Math.Abs(b);
14+
1615
if (a == 0)
1716
return b;
1817
if (b == 0)
1918
return a;
19+
if (a == b)
20+
return a;
2021

21-
uint _a = a, _b = b;
22-
23-
//Bitwise operator '&' works on individual bits of each value
24-
//result is 0 or 1
25-
//it works like a modulus operator '%' but is more efficient
26-
uint r = _a & _b;
22+
return Euclidean(a, b);
23+
}
2724

28-
while(r != 0)
29-
{
30-
_a = _b;
31-
_b = r;
32-
r = _a & _b;
33-
}
25+
private static int Euclidean(int a, int b)
26+
{
27+
if (b == 0)
28+
return a;
3429

35-
return _b;
30+
return Euclidean(b, a % b);
3631
}
3732

3833
/// <summary>
39-
/// Determines given two numbers are relatively prime
34+
/// Returns the greatest common divisor of two numbers using Stein Algorithm.
4035
/// </summary>
41-
public static bool IsRelativelyPrime(uint a, uint b)
36+
public static int FindGCDStein(int a, int b)
37+
{
38+
a = Math.Abs(a);
39+
b = Math.Abs(b);
40+
41+
return Stein(a, b);
42+
}
43+
44+
private static int Stein(int a, int b)
4245
{
43-
return FindGCD(a, b) == 1;
46+
if (a == 0)
47+
return b;
48+
if (b == 0)
49+
return a;
50+
if (a == b)
51+
return a;
52+
53+
if ((~a & 1) == 1)
54+
{
55+
if ((b & 1) == 1)
56+
{
57+
return Stein(a >> 1, b);
58+
}
59+
else
60+
{
61+
return Stein(a >> 1, b >> 1) << 1;
62+
}
63+
}
64+
65+
if ((~b & 1) == 1)
66+
{
67+
return Stein(a, b >> 1);
68+
}
69+
70+
return a > b ? Stein((a - b) >> 1, b) : Stein(a, (b - a) >> 1);
4471
}
4572
}
4673
}

UnitTest/AlgorithmsTests/GreatestCommonDivisorTest.cs

Lines changed: 0 additions & 74 deletions
This file was deleted.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using Algorithms.Numeric;
2+
using Xunit;
3+
4+
namespace UnitTest.AlgorithmsTests
5+
{
6+
public class GreatestCommonDivisorTests
7+
{
8+
[Fact]
9+
public void FindGCD_BothAreZero()
10+
{
11+
var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(0, 0);
12+
Assert.Equal(0, gcdEuclidean);
13+
14+
var gcdStein = GreatestCommonDivisor.FindGCDStein(0, 0);
15+
Assert.Equal(0, gcdStein);
16+
}
17+
18+
[Theory]
19+
[InlineData(0, 4, 4)]
20+
[InlineData(0, 9, 9)]
21+
[InlineData(0, -14, 14)]
22+
[InlineData(0, -99, 99)]
23+
public void FindGCD_FirstIsZero(int a, int b, int expected)
24+
{
25+
var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b);
26+
Assert.Equal(expected, gcdEuclidean);
27+
28+
var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b);
29+
Assert.Equal(expected, gcdStein);
30+
}
31+
32+
[Theory]
33+
[InlineData(4, 0, 4)]
34+
[InlineData(9, 0, 9)]
35+
[InlineData(-14, 0, 14)]
36+
[InlineData(-99, 0, 99)]
37+
public void FindGCD_SecondIsZero(int a, int b, int expected)
38+
{
39+
var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b);
40+
Assert.Equal(expected, gcdEuclidean);
41+
42+
var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b);
43+
Assert.Equal(expected, gcdStein);
44+
}
45+
46+
[Theory]
47+
[InlineData(2, 4, 2)]
48+
[InlineData(27, 9, 9)]
49+
[InlineData(27, 14, 1)]
50+
[InlineData(9, 6, 3)]
51+
public void FindGCD_BothNumberArePositive(int a, int b, int expected)
52+
{
53+
var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b);
54+
Assert.Equal(expected, gcdEuclidean);
55+
56+
var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b);
57+
Assert.Equal(expected, gcdStein);
58+
}
59+
60+
[Theory]
61+
[InlineData(-2, -4, 2)]
62+
[InlineData(-27, -9, 9)]
63+
[InlineData(-27, -14, 1)]
64+
[InlineData(-9, -6, 3)]
65+
public void FindGCD_BothNumberAreNegative(int a, int b, int expected)
66+
{
67+
var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b);
68+
Assert.Equal(expected, gcdEuclidean);
69+
70+
var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b);
71+
Assert.Equal(expected, gcdStein);
72+
}
73+
74+
[Theory]
75+
[InlineData(2, -4, 2)]
76+
[InlineData(-27, 9, 9)]
77+
[InlineData(27, -14, 1)]
78+
[InlineData(-9, 6, 3)]
79+
public void FindGCD_CombinationPositiveAndNegative(int a, int b, int expected)
80+
{
81+
var gcdEuclidean = GreatestCommonDivisor.FindGCDEuclidean(a, b);
82+
Assert.Equal(expected, gcdEuclidean);
83+
84+
var gcdStein = GreatestCommonDivisor.FindGCDStein(a, b);
85+
Assert.Equal(expected, gcdStein);
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)