1
0

3 Commits

Author SHA1 Message Date
7379b8cb65 enhance tests 2024-09-04 21:15:09 +03:00
090ea89a1c add IntegralCalculator.getAccuracy 2024-09-04 21:14:46 +03:00
b9ff4e9f62 dont throw if lowerBound is greater than upperBound
.
2024-09-04 21:14:46 +03:00
2 changed files with 57 additions and 14 deletions

View File

@@ -27,6 +27,15 @@ public class IntegralCalculator {
this.accuracy = accuracy;
}
/**
* Returns the accuracy level used for the integration calculation.
*
* @return The accuracy level as a double.
*/
public double getAccuracy() {
return this.accuracy;
}
/**
* Calculates the definite integral of the specified function over a given interval
* using the trapezoidal rule.
@@ -35,15 +44,20 @@ public class IntegralCalculator {
* @param lowerBound The lower bound of the integration interval.
* @param upperBound The upper bound of the integration interval.
* @return The estimated value of the definite integral.
* @throws IllegalArgumentException if {@code lowerBound} is greater than {@code upperBound}.
*/
public double calculate(Function<Double, Double> function, double lowerBound, double upperBound) {
if (lowerBound > upperBound)
throw new IllegalArgumentException("lowerBound must be <= upperBound");
if (lowerBound == upperBound)
return 0.0;
var invert = false;
if (lowerBound > upperBound) {
invert = true;
var temp = lowerBound;
lowerBound = upperBound;
upperBound = temp;
}
var n = (long) Math.ceil((upperBound - lowerBound) / this.accuracy);
var h = (upperBound - lowerBound) / n;
@@ -53,6 +67,9 @@ public class IntegralCalculator {
sum *= h;
if (invert)
sum = -sum;
return sum;
}
}

View File

@@ -1,27 +1,53 @@
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import ru.lionarius.IntegralCalculator;
import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.*;
class IntegralCalculatorTests {
private static void assertIntegral(final double expected, final IntegralCalculator calculator, final Function<Double, Double> function, final double lowerBound, final double upperBound) {
var value = calculator.calculate(function, lowerBound, upperBound);
assertEquals(value, expected, calculator.getAccuracy());
}
@Test
void integralOfSinX_X() {
void accuracyValidRange() {
assertThrowsExactly(IllegalArgumentException.class, () -> new IntegralCalculator(0.0));
assertThrowsExactly(IllegalArgumentException.class, () -> new IntegralCalculator(-0.0));
assertThrowsExactly(IllegalArgumentException.class, () -> new IntegralCalculator(-1.0));
assertDoesNotThrow(() -> new IntegralCalculator(Double.MIN_VALUE));
}
@Test
void accuracy_SinXX() {
final var actualValue = 0.30116867893975678925156571418732239589025264018044883800265445461081000961676790443;
Function<Double, Double> function = x -> Math.sin(x) * x;
var lowerBound = 0.0;
var upperBound = 1.0;
double[] accuracies = {0.001, 0.00001, 0.0000001, 0.000000001};
final Function<Double, Double> function = x -> Math.sin(x) * x;
final var lowerBound = 0.0;
final var upperBound = 1.0;
final double[] accuracies = {0.001, 0.00001, 0.0000001};
for (var accuracy : accuracies) {
var calculator = new IntegralCalculator(accuracy);
var value = calculator.calculate(function, lowerBound, upperBound);
var delta = Math.abs(value - actualValue);
assertTrue(delta <= accuracy, "Expected accuracy of " + accuracy + ", got " + delta);
assertIntegral(actualValue, calculator, function, lowerBound, upperBound);
}
}
@Test
void bounds_X() {
final var calculator = new IntegralCalculator(0.1);
final Function<Double, Double> function = x -> x;
final var lowerBound = 0.0;
final var upperBound = 1.0;
assertIntegral(0.5, calculator, function, lowerBound, upperBound);
assertIntegral(-0.5, calculator, function, upperBound, lowerBound);
assertIntegral(0.0, calculator, function, lowerBound, lowerBound);
}
}