1
0
This commit is contained in:
2024-09-05 11:12:24 +03:00
parent bf57e58447
commit 19883103ed
2 changed files with 86 additions and 13 deletions

View File

@@ -1,5 +1,6 @@
package ru.lionarius; package ru.lionarius;
import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
/** /**
@@ -14,6 +15,29 @@ public class IntegralCalculator {
*/ */
private final double accuracy; private final double accuracy;
/**
* A callback to track the progress of the integration.
* The callback is called at least twice: once at the beginning, and once at the end of computation.
* Takes the current step and the total number of steps.
*/
private final BiConsumer<Long, Long> progressCallback;
/**
* Constructs an {@link IntegralCalculator} with the specified accuracy and an optional progress callback.
* The progress callback is invoked at each step of the integration process.
*
* @param accuracy The desired accuracy for the integral calculation.
* @param progressCallback A callback function to track progress. Can be null.
* @throws IllegalArgumentException if the accuracy is less than or equal to zero.
*/
public IntegralCalculator(double accuracy, BiConsumer<Long, Long> progressCallback) {
if (accuracy <= 0.0)
throw new IllegalArgumentException("accuracy must be a positive number");
this.accuracy = accuracy;
this.progressCallback = progressCallback;
}
/** /**
* Constructs an {@link IntegralCalculator} with the specified accuracy. * Constructs an {@link IntegralCalculator} with the specified accuracy.
* *
@@ -21,10 +45,7 @@ public class IntegralCalculator {
* @throws IllegalArgumentException if the accuracy is less than or equal to zero. * @throws IllegalArgumentException if the accuracy is less than or equal to zero.
*/ */
public IntegralCalculator(double accuracy) { public IntegralCalculator(double accuracy) {
if (accuracy <= 0.0) this(accuracy, null);
throw new IllegalArgumentException("accuracy must be a positive number");
this.accuracy = accuracy;
} }
/** /**
@@ -46,8 +67,12 @@ public class IntegralCalculator {
* @return The estimated value of the definite integral. * @return The estimated value of the definite integral.
*/ */
public double calculate(Function<Double, Double> function, double lowerBound, double upperBound) { public double calculate(Function<Double, Double> function, double lowerBound, double upperBound) {
if (lowerBound == upperBound) if (lowerBound == upperBound) {
this.callProgressCallback(0, 1);
this.callProgressCallback(1, 1);
return 0.0; return 0.0;
}
var invert = false; var invert = false;
if (lowerBound > upperBound) { if (lowerBound > upperBound) {
@@ -61,15 +86,33 @@ public class IntegralCalculator {
var n = (long) Math.ceil((upperBound - lowerBound) / this.accuracy); var n = (long) Math.ceil((upperBound - lowerBound) / this.accuracy);
var h = (upperBound - lowerBound) / n; var h = (upperBound - lowerBound) / n;
this.callProgressCallback(0, n);
var sum = (function.apply(lowerBound) + function.apply(upperBound)) / 2; var sum = (function.apply(lowerBound) + function.apply(upperBound)) / 2;
for (var i = 1L; i < n; i++) for (var i = 1L; i < n; i++) {
sum += function.apply(lowerBound + h * i); sum += function.apply(lowerBound + h * i);
this.callProgressCallback(i, n);
}
sum *= h; sum *= h;
if (invert) if (invert)
sum = -sum; sum = -sum;
this.callProgressCallback(n, n);
return sum; return sum;
} }
/**
* Calls the progress callback, if provided.
*
* @param current The current step in the integration process.
* @param total The total number of steps in the integration process.
*/
private void callProgressCallback(long current, long total) {
if (this.progressCallback != null)
this.progressCallback.accept(current, total);
}
} }

View File

@@ -7,10 +7,24 @@ public class Main {
Function<Double, Double> function = x -> Math.sin(x) * x; Function<Double, Double> function = x -> Math.sin(x) * x;
var lowerBound = 0.0; var lowerBound = 0.0;
var upperBound = 1.0; var upperBound = 1.0;
double[] accuracies = {0.001, 0.00001, 0.0000001, 0.000000001}; double[] accuracies = {0.001, 0.00001, 0.0000001, 0.000000001, 0.000000001};
var threads = new Thread[accuracies.length];
for (var accuracy : accuracies) { for (var i = 0; i < accuracies.length; i++) {
var calculator = new IntegralCalculator(accuracy); final var accuracy = accuracies[i];
var thread = new Thread(() -> {
var calculator = new IntegralCalculator(
accuracy,
(current, total) -> {
if (current % (total / 15) != 0)
return;
System.out.printf(
"[%s] Progress: %.2f%%%n",
Thread.currentThread().getName(),
(current * 100.0 / total)
);
}
);
var startTime = System.nanoTime(); var startTime = System.nanoTime();
@@ -18,7 +32,23 @@ public class Main {
var totalTime = System.nanoTime() - startTime; var totalTime = System.nanoTime() - startTime;
System.out.printf("Calculated value: %.15f | Accuracy: %e | Time: %.9fms%n", value, accuracy, totalTime / 1_000_000.0); System.out.printf(
"[%s] Calculated value: %.15f | Accuracy: %e | Time: %.9fms%n",
Thread.currentThread().getName(),
value,
accuracy,
totalTime / 1_000_000.0
);
});
threads[i] = thread;
thread.start();
}
try {
for (var thread : threads)
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} }
} }
} }