lab2
This commit is contained in:
@@ -3,7 +3,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = 'ru.lionarius'
|
group = 'ru.lionarius'
|
||||||
version = '1-LAB'
|
version = '2-LAB'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|||||||
75
src/main/java/ru/lionarius/IntegralCalculator.java
Normal file
75
src/main/java/ru/lionarius/IntegralCalculator.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package ru.lionarius;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that provides a numerical method to calculate definite integrals of a given function.
|
||||||
|
* The integration is performed using the trapezoidal rule, with a specified accuracy.
|
||||||
|
*/
|
||||||
|
public class IntegralCalculator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accuracy level for the integration process.
|
||||||
|
* A smaller value results in higher accuracy but more computation time.
|
||||||
|
*/
|
||||||
|
private final double accuracy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an {@link IntegralCalculator} with the specified accuracy.
|
||||||
|
*
|
||||||
|
* @param accuracy The desired accuracy for the integral calculation
|
||||||
|
* @throws IllegalArgumentException if the accuracy is less than or equal to zero.
|
||||||
|
*/
|
||||||
|
public IntegralCalculator(double accuracy) {
|
||||||
|
if (accuracy <= 0.0)
|
||||||
|
throw new IllegalArgumentException("accuracy must be a positive number");
|
||||||
|
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param function The function to integrate.
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
public double calculate(Function<Double, Double> function, double lowerBound, double 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;
|
||||||
|
|
||||||
|
var sum = (function.apply(lowerBound) + function.apply(upperBound)) / 2;
|
||||||
|
for (var i = 1L; i < n; i++)
|
||||||
|
sum += function.apply(lowerBound + h * i);
|
||||||
|
|
||||||
|
sum *= h;
|
||||||
|
|
||||||
|
if (invert)
|
||||||
|
sum = -sum;
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,24 @@
|
|||||||
package ru.lionarius;
|
package ru.lionarius;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
System.out.println("Hello world!");
|
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};
|
||||||
|
|
||||||
|
for (var accuracy : accuracies) {
|
||||||
|
var calculator = new IntegralCalculator(accuracy);
|
||||||
|
|
||||||
|
var startTime = System.nanoTime();
|
||||||
|
|
||||||
|
var value = calculator.calculate(function, lowerBound, upperBound);
|
||||||
|
|
||||||
|
var totalTime = System.nanoTime() - startTime;
|
||||||
|
|
||||||
|
System.out.printf("Calculated value: %.15f | Accuracy: %e | Time: %.9fms%n", value, accuracy, totalTime / 1_000_000.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
src/test/java/IntegralCalculatorTests.java
Normal file
53
src/test/java/IntegralCalculatorTests.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
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 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user