mirror of
https://github.com/TheAlgorithms/Java.git
synced 2026-03-13 08:40:43 +08:00
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:
61
src/main/java/com/thealgorithms/maths/Neville.java
Normal file
61
src/main/java/com/thealgorithms/maths/Neville.java
Normal 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];
|
||||
}
|
||||
}
|
||||
69
src/test/java/com/thealgorithms/maths/NevilleTest.java
Normal file
69
src/test/java/com/thealgorithms/maths/NevilleTest.java
Normal 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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user