feat: Add Neville's Algorithm (#6842)

* feat: Add Neville's algorithm for polynomial interpolation

* Update Neville.java

* style: Fix linter formatting issues.

* Handled Div by Zero Case

* Update NevilleTest.java

* Update Neville.java

* Update NevilleTest.java

* Update Neville.java
This commit is contained in:
Keykyrios
2025-10-28 15:44:59 +05:30
committed by GitHub
parent 14a0de4181
commit 3c70a54355
2 changed files with 130 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
package com.thealgorithms.maths;
import java.util.HashSet;
import java.util.Set;
/**
* In numerical analysis, Neville's algorithm is an algorithm used for
* polynomial interpolation. Given n+1 points, there is a unique polynomial of
* degree at most n that passes through all the points. Neville's algorithm
* computes the value of this polynomial at a given point.
*
* <p>
* Wikipedia: https://en.wikipedia.org/wiki/Neville%27s_algorithm
*
* @author Mitrajit Ghorui(KeyKyrios)
*/
public final class Neville {
private Neville() {
}
/**
* Evaluates the polynomial that passes through the given points at a
* specific x-coordinate.
*
* @param x The x-coordinates of the points. Must be the same length as y.
* @param y The y-coordinates of the points. Must be the same length as x.
* @param target The x-coordinate at which to evaluate the polynomial.
* @return The interpolated y-value at the target x-coordinate.
* @throws IllegalArgumentException if the lengths of x and y arrays are
* different, if the arrays are empty, or if x-coordinates are not unique.
*/
public static double interpolate(double[] x, double[] y, double target) {
if (x.length != y.length) {
throw new IllegalArgumentException("x and y arrays must have the same length.");
}
if (x.length == 0) {
throw new IllegalArgumentException("Input arrays cannot be empty.");
}
// Check for duplicate x-coordinates to prevent division by zero
Set<Double> seenX = new HashSet<>();
for (double val : x) {
if (!seenX.add(val)) {
throw new IllegalArgumentException("Input x-coordinates must be unique.");
}
}
int n = x.length;
double[] p = new double[n];
System.arraycopy(y, 0, p, 0, n); // Initialize p with y values
for (int k = 1; k < n; k++) {
for (int i = 0; i < n - k; i++) {
p[i] = ((target - x[i + k]) * p[i] + (x[i] - target) * p[i + 1]) / (x[i] - x[i + k]);
}
}
return p[0];
}
}

View File

@@ -0,0 +1,69 @@
package com.thealgorithms.maths;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
public class NevilleTest {
@Test
public void testInterpolateLinear() {
// Test with a simple linear function y = 2x + 1
// Points (0, 1) and (2, 5)
double[] x = {0, 2};
double[] y = {1, 5};
// We want to find y when x = 1, which should be 3
double target = 1;
double expected = 3.0;
assertEquals(expected, Neville.interpolate(x, y, target), 1e-9);
}
@Test
public void testInterpolateQuadratic() {
// Test with a quadratic function y = x^2
// Points (0, 0), (1, 1), (3, 9)
double[] x = {0, 1, 3};
double[] y = {0, 1, 9};
// We want to find y when x = 2, which should be 4
double target = 2;
double expected = 4.0;
assertEquals(expected, Neville.interpolate(x, y, target), 1e-9);
}
@Test
public void testInterpolateWithNegativeNumbers() {
// Test with y = x^2 - 2x + 1
// Points (-1, 4), (0, 1), (2, 1)
double[] x = {-1, 0, 2};
double[] y = {4, 1, 1};
// We want to find y when x = 1, which should be 0
double target = 1;
double expected = 0.0;
assertEquals(expected, Neville.interpolate(x, y, target), 1e-9);
}
@Test
public void testMismatchedArrayLengths() {
double[] x = {1, 2};
double[] y = {1};
double target = 1.5;
assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target));
}
@Test
public void testEmptyArrays() {
double[] x = {};
double[] y = {};
double target = 1;
assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target));
}
@Test
public void testDuplicateXCoordinates() {
double[] x = {1, 2, 1};
double[] y = {5, 8, 3};
double target = 1.5;
assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target));
}
}