Skip to content

Commit 3074384

Browse files
authored
Fix gcd (keon#760)
* fix: add input argument checks and lcm/gcd can handle negative numbers * test: add new tests for gcd/lcm to test new fixes
1 parent 68be49c commit 3074384

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

algorithms/maths/gcd.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
def gcd(a, b):
22
"""Computes the greatest common divisor of integers a and b using
33
Euclid's Algorithm.
4+
gcd{𝑎,𝑏}=gcd{−𝑎,𝑏}=gcd{𝑎,−𝑏}=gcd{−𝑎,−𝑏}
5+
See proof: https://proofwiki.org/wiki/GCD_for_Negative_Integers
46
"""
7+
a_int = isinstance(a, int)
8+
b_int = isinstance(b, int)
9+
a = abs(a)
10+
b = abs(b)
11+
if not(a_int or b_int):
12+
raise ValueError("Input arguments are not integers")
13+
14+
if (a == 0) or (b == 0) :
15+
raise ValueError("One or more input arguments equals zero")
16+
517
while b != 0:
618
a, b = b, a % b
719
return a
820

921

1022
def lcm(a, b):
1123
"""Computes the lowest common multiple of integers a and b."""
12-
return a * b / gcd(a, b)
24+
return abs(a) * abs(b) / gcd(a, b)
1325

1426

1527
"""

tests/test_maths.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
)
3030

3131
import unittest
32+
import pytest
3233

3334

3435
class TestPower(unittest.TestCase):
@@ -128,8 +129,37 @@ def test_gcd(self):
128129
self.assertEqual(4, gcd(8, 12))
129130
self.assertEqual(1, gcd(13, 17))
130131

132+
def test_gcd_non_integer_input(self):
133+
with pytest.raises(ValueError, match=r"Input arguments are not integers"):
134+
gcd(1.0, 5)
135+
gcd(5, 6.7)
136+
gcd(33.8649, 6.12312312)
137+
138+
def test_gcd_zero_input(self):
139+
with pytest.raises(ValueError, match=r"One or more input arguments equals zero"):
140+
gcd(0, 12)
141+
gcd(12, 0)
142+
gcd(0, 0)
143+
144+
def test_gcd_negative_input(self):
145+
self.assertEqual(1, gcd(-13, -17))
146+
self.assertEqual(4, gcd(-8, 12))
147+
self.assertEqual(8, gcd(24, -16))
148+
131149
def test_lcm(self):
132150
self.assertEqual(24, lcm(8, 12))
151+
self.assertEqual(5767, lcm(73, 79))
152+
153+
def test_lcm_negative_numbers(self):
154+
self.assertEqual(24, lcm(-8, -12))
155+
self.assertEqual(5767, lcm(73, -79))
156+
self.assertEqual(1, lcm(-1, 1))
157+
158+
def test_lcm_zero_input(self):
159+
with pytest.raises(ValueError, match=r"One or more input arguments equals zero"):
160+
lcm(0, 12)
161+
lcm(12, 0)
162+
lcm(0, 0)
133163

134164
def test_trailing_zero(self):
135165
self.assertEqual(1, trailing_zero(34))
@@ -140,6 +170,7 @@ def test_gcd_bit(self):
140170
self.assertEqual(1, gcd(13, 17))
141171

142172

173+
143174
class TestGenerateStroboGrammatic(unittest.TestCase):
144175
"""[summary]
145176
Test for the file generate_strobogrammatic.py

0 commit comments

Comments
 (0)