From 19883103ed79c40d2f5803c34987c7442ddeadba Mon Sep 17 00:00:00 2001 From: lionarius Date: Thu, 5 Sep 2024 11:12:24 +0300 Subject: [PATCH] lab3 --- .../java/ru/lionarius/IntegralCalculator.java | 55 +++++++++++++++++-- src/main/java/ru/lionarius/Main.java | 44 ++++++++++++--- 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/main/java/ru/lionarius/IntegralCalculator.java b/src/main/java/ru/lionarius/IntegralCalculator.java index ae1bc66..207c225 100644 --- a/src/main/java/ru/lionarius/IntegralCalculator.java +++ b/src/main/java/ru/lionarius/IntegralCalculator.java @@ -1,5 +1,6 @@ package ru.lionarius; +import java.util.function.BiConsumer; import java.util.function.Function; /** @@ -14,6 +15,29 @@ public class IntegralCalculator { */ 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 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 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. * @@ -21,10 +45,7 @@ public class IntegralCalculator { * @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; + this(accuracy, null); } /** @@ -46,8 +67,12 @@ public class IntegralCalculator { * @return The estimated value of the definite integral. */ public double calculate(Function function, double lowerBound, double upperBound) { - if (lowerBound == upperBound) + if (lowerBound == upperBound) { + this.callProgressCallback(0, 1); + this.callProgressCallback(1, 1); + return 0.0; + } var invert = false; if (lowerBound > upperBound) { @@ -61,15 +86,33 @@ public class IntegralCalculator { var n = (long) Math.ceil((upperBound - lowerBound) / this.accuracy); var h = (upperBound - lowerBound) / n; + this.callProgressCallback(0, n); + 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); + this.callProgressCallback(i, n); + } + sum *= h; if (invert) sum = -sum; + this.callProgressCallback(n, n); + 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); + } } diff --git a/src/main/java/ru/lionarius/Main.java b/src/main/java/ru/lionarius/Main.java index a9563d6..4498efa 100644 --- a/src/main/java/ru/lionarius/Main.java +++ b/src/main/java/ru/lionarius/Main.java @@ -7,18 +7,48 @@ public class Main { Function function = x -> Math.sin(x) * x; var lowerBound = 0.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) { - var calculator = new IntegralCalculator(accuracy); + for (var i = 0; i < accuracies.length; i++) { + 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(); - var value = calculator.calculate(function, lowerBound, upperBound); + var value = calculator.calculate(function, lowerBound, upperBound); - 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); } } }