Задача: Численно убедиться в справедливости равенства, для чего для заданного значения аргумента [latex]x[/latex] вычислить левую его часть и разложение, стоящее в правой части с заданной погрешностью [latex]\varepsilon [/latex]. Испытать разложение на сходимость при разных значениях аргумента, найти скорость сходимости, для чего вывести число итераций [latex]n[/latex] (слагаемых или сомножителей), необходимых для достижения заданной точности. В некоторых задачах указан интервал допустимых значений аргумента [latex]x[/latex], при которых сходимость гарантируется.
[latex]\ln \left(1-x \right)=-\left(x+\frac{x^{2}}{2}+\frac{x^{3}}{3}+\cdot \cdot \cdot +\frac{x^{n}}{n}+\cdot \cdot \cdot \right)[/latex], [latex]x<1[/latex][latex]x[/latex] | [latex]eps[/latex] | Левая часть | Правая часть | Количество шагов |
0.1 | 0.001 | -0.105361 | -0.105 | 3 |
0.1 | 0.000001 | -0.105361 | -0.105360 | 6 |
0.5 | 0.001 | -0.693147 | -0.692262 | 8 |
0.5 | 0.000001 | -0.693147 | -0.693146 | 17 |
0.95 | 0.001 | -2.995732 | -2.994775 | 101 |
0.95 | 0.000001 | -2.995732 | -2.995731 | 222 |
C++:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <stdio.h> #include <math.h> int main(void) { double x, eps;//Вводит пользователь. double a, b=0, c=1;//Используются для вычислений. int n=1; printf("Введите аргумент x<1 и погрешность eps.\n"); scanf("%lf %lf\n", &x, &eps); a=log(1-x); for (int i=1; fabs(a-b)>=eps; i++, n++) { c=c*x;//Степени х. b=b-c/i;//Сумма. } printf("Результат в левой части: %lf.\n", a); printf("Результат в правой части: %lf.\n", b); printf("Количество шагов: %d.\n", n); return 0; } |
Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import java.util.*; import java.lang.*; import java.io.*; class Ideone { public static void main (String[] args) { Scanner in = new Scanner(System.in); double x, eps;//Вводит пользователь. double a, b=0, c=1;//Используются для вычислений. int n=1; System.out.println("Введите аргумент x<1 и погрешность eps."); x = in.nextDouble(); eps = in.nextDouble(); a = Math.log(1-x); for (int i=1; Math.abs(a-b)>=eps; i++, n++) { c=c*x;//Степени х. b=b-c/i;//Сумма. } System.out.println("Результат в левой части: "+a); System.out.println("Результат в правой части: "+b); System.out.println("Количество шагов: "+n); } } |
Для переменных [latex]x, eps, a, b, c[/latex] я использовала double, так как [latex]x<1[/latex] и [latex]eps[/latex] ([latex]\varepsilon [/latex]) — вещественные числа, которые вводит пользователь, [latex]a, b, c[/latex] используются для вычислений, поэтому тоже вещественные. Для переменной [latex]n[/latex] (в неё записывается количество шагов цикла) я использовала тип int, т.к. это целые числа.
Сперва вычисляем значение переменной [latex]a[/latex] — левую часть равенства.
Для вычисления правой части используем цикл for, который работает пока [latex]\left|a-b \right|\geq eps[/latex] (т.е. различие между правой и левой частью больше, чем погрешность, заданная пользователем).
При каждом шаге переменная [latex]n[/latex] увеличивается на единицу для подсчёта скорости сходимости.
Переменная [latex]c[/latex] обозначает элемент суммы, а [latex]b[/latex] — сумму элементов в правой части равенства.
Эта задача на Ideone:
C++
Java
Вы получили ответ «Не хватило шагов.» на третьем тесте, видимо, потому, что забыли присвоить переменной n (количество шагов) начальное значение. Вот отсчет шагов у Вас и начался не с нуля
У Вас в отчете написано модуль a-b больше eps и n < limit, а в программе меньше или равно и больше или равно соответственно. Что из этого верно?
Чтобы оценить «скорость сходимости» нужно для одного и того же x посчитать значение с разной точностью (все лучшей и лучшей точностью) и посмотреть как увеличивается необходимое количество слагаемых. И этот процесс желательно проделать при разных значениях x, например 0.1, 0.5 и 0.9, как Вы выбрали.
Вместо функции pow степень можно вычислять рекуррентно, домножая уже подсчитанную степень на x.
Исправлено.
Вы не исправили:
«Вместо функции pow степень можно вычислять рекуррентно, домножая уже подсчитанную степень на x.»
В коде на ideone рекуррентное вычисление есть,
но совсем не того, что нужно. Прочтите внимательно — рекуррентно у Вас можно считать только степень. А Вы еще и на i делите. В результате в знаменателе получаете факториал. Конечно, никаких шагов не хватит — левая и правая части у Вас не будут сближаться. А сходиться должно очень быстро.
0.1 0.0001 — 4 шага
0.95 0.0002 — 128 шагов (что это за ограничение в 100 шагов?)
0.95 1e-12 — 477 шагов
Будьте внимательны. Повторные проверки отнимают время у нас и заставляют Вас ждать заранее известного ответа. Да и повторные проверки обнаруживают новые недочёты.
Теперь точно исправила. Я так поняла, ограничивать количество шагов не нужно?
Принято
Java версия засчитана, 10 баллов — хотя переменные a,b и неплохо бы назвать более логично.