Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.thealgorithms.maths;

/**
* In mathematics, the extended Euclidean algorithm is an extension to the
* Euclidean algorithm, and computes, in addition to the greatest common divisor
* (gcd) of integers a and b, also the coefficients of Bézout's identity, which
* are integers x and y such that ax + by = gcd(a, b).
*
* <p>
* For more details, see
* https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
*/
public final class ExtendedEuclideanAlgorithm {

private ExtendedEuclideanAlgorithm() {
}

/**
* This method implements the extended Euclidean algorithm.
*
* @param a The first number.
* @param b The second number.
* @return An array of three integers:
* <ul>
* <li>Index 0: The greatest common divisor (gcd) of a and b.</li>
* <li>Index 1: The value of x in the equation ax + by = gcd(a, b).</li>
* <li>Index 2: The value of y in the equation ax + by = gcd(a, b).</li>
* </ul>
*/
public static long[] extendedGCD(long a, long b) {
if (b == 0) {
// Base case: gcd(a, 0) = a. The equation is a*1 + 0*0 = a.
return new long[] {a, 1, 0};
}

// Recursive call
long[] result = extendedGCD(b, a % b);
long gcd = result[0];
long x1 = result[1];
long y1 = result[2];

// Update coefficients using the results from the recursive call
long x = y1;
long y = x1 - a / b * y1;

return new long[] {gcd, x, y};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.thealgorithms.maths;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class ExtendedEuclideanAlgorithmTest {

/**
* Verifies that the returned values satisfy Bézout's identity: a*x + b*y =
* gcd(a, b)
*/
private void verifyBezoutIdentity(long a, long b, long[] result) {
long gcd = result[0];
long x = result[1];
long y = result[2];
assertEquals(a * x + b * y, gcd, "Bézout's identity failed for gcd(" + a + ", " + b + ")");
}

@Test
public void testExtendedGCD() {
// Test case 1: General case gcd(30, 50) = 10
long[] result1 = ExtendedEuclideanAlgorithm.extendedGCD(30, 50);
assertEquals(10, result1[0], "Test Case 1 Failed: gcd(30, 50) should be 10");
verifyBezoutIdentity(30, 50, result1);

// Test case 2: Another general case gcd(240, 46) = 2
long[] result2 = ExtendedEuclideanAlgorithm.extendedGCD(240, 46);
assertEquals(2, result2[0], "Test Case 2 Failed: gcd(240, 46) should be 2");
verifyBezoutIdentity(240, 46, result2);

// Test case 3: Base case where b is 0, gcd(10, 0) = 10
long[] result3 = ExtendedEuclideanAlgorithm.extendedGCD(10, 0);
assertEquals(10, result3[0], "Test Case 3 Failed: gcd(10, 0) should be 10");
verifyBezoutIdentity(10, 0, result3);

// Test case 4: Numbers are co-prime gcd(17, 13) = 1
long[] result4 = ExtendedEuclideanAlgorithm.extendedGCD(17, 13);
assertEquals(1, result4[0], "Test Case 4 Failed: gcd(17, 13) should be 1");
verifyBezoutIdentity(17, 13, result4);

// Test case 5: One number is a multiple of the other gcd(100, 20) = 20
long[] result5 = ExtendedEuclideanAlgorithm.extendedGCD(100, 20);
assertEquals(20, result5[0], "Test Case 5 Failed: gcd(100, 20) should be 20");
verifyBezoutIdentity(100, 20, result5);
}
}