Задача
Численно убедиться в справедливости равенства, для чего для заданного значения аргумента [latex]x[/latex] вычислить левую его часть и разложение, стоящее в правой части, с заданной погрешностью [latex]\varepsilon[/latex]. Испытать разложение на сходимость при разных значениях аргумента, оценить скорость сходимости, для чего вывести число итераций [latex]n[/latex] (слагаемых или сомножителей), необходимых для достижения заданной точности.
[latex]\frac { { e }^{ x }+{ e }^{ -x } }{ 2 } =1+\frac { { x }^{ 2 } }{ 2! } +\frac { { x }^{ 4 } }{ 4! } +\cdots+\frac { { x }^{ 2n } }{ (2n)! } +\cdots[/latex]Тесты
x | [latex]\varepsilon[/latex] | Левая часть | Правая часть | n | Разность | Комментарий |
3 | 0.00005 | 10.0676619958 | 10.0676598764 | 8 | 0.0000021194 | Пройден |
11.33 | 0.0000314 | 41641.5114284855 | 41641.5114045419 | 19 | 0.0000239436 | Пройден |
6 | 0 | Погрешность равна 0, тогда правая часть стремится к левой 201.7156361225 (n=бесконечность) | Не пройден |
Код программы на C++:
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 29 30 31 |
#include <iostream> #include <math.h> int main() { double E, x, dife, left, right = 0.0, u = 1.0 ; int n = 0;//Описание переменных для хранения входных данных.// scanf("%lf %lf", &x, &E); //Чтение из стандартного потока ввода.// left = ( pow (M_E , x) + pow (M_E , -x) ) / 2; //Расчет левой части равенства. if (E != 0) //Критерий, при котором программа может быть выполнена// { do //Цикл программы (для подсчета правой части равенства). { n ++; right += u ; u *= x * x / ( (2 * n - 1) * 2 * n ); dife = left - right; //Вычисление разности значения левой части и правой части// } while(dife > fabs(E)); //Конечный критерий, при котором цикл останавливается// //Вывод окончательных результатов на экран// printf("Левая часть равна = %.10lf \nПравая часть равна = %.10lf \n",left,right); printf("После n=%d исследуемое выражение отличается от левой части менее, чем на %.10lf, ",n,fabs(E)); printf("а именно на %.10lf \n",fabs(dife)); } else { //Вывод оповещения о неправильном вводе данных (при несоответствии начальному критерию).// if (fabs(E) == 0) { printf("Погрешность равна 0, тогда правая часть стремится к левой %.10lf (n=бесконечность)",left); } } return 0; } |
Для этого вначале высчитывалось значение левой части [latex]\frac { { e }^{ x }+{ e }^{ -x } }{ 2 } [/latex] при заданном [latex]x[/latex], а далее, в цикле, высчитывалось значение правой части [latex]\frac { { x }^{ 2 } }{ 2! } +\frac { { x }^{ 4 } }{ 4! } +…+\frac { { x }^{ 2n } }{ (2n)! } +…[/latex]. В цикле программа находила последующий элемент последовательности, стоящей в правой части равенства, каждый раз умножая предыдущий элемент на [latex]\frac { { x }^{ 2 } }{ (2n-1)*(2n) } [/latex] до тех пор пока разность между левой и правой частью равенства [latex]dife=left-right[/latex] не стала меньше заданной погрешности, заданной по модулю [latex]dife < \left|\varepsilon \right|[/latex]. После завершения цикла программа запоминает последнее значение [latex]n[/latex] и после этого выводит его на экран.
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 29 30 31 32 33 |
import java.util.*; import java.lang.*; import java.io.*; class Equation { public static void main (String[] args) throws java.lang.Exception { //Описание переменных для хранения входных данных.// Scanner in = new Scanner(System.in); double eps = in.nextDouble(); double x = in.nextDouble(); double difference, right = 0.0, tmp = 1.0; double left = (Math.pow(Math.E, x) + Math.pow(Math.E , -x)) / 2; //Расчет левой части равенства. int n = 0; if (eps != 0){ //Критерий, при котором программа может быть выполнена// do{ //Цикл программы (для подсчета правой части равенства). n ++; right += tmp ; tmp *= x * x / ((2 * n - 1) * 2 * n); difference = left - right; //Вычисление разности значения левой части и правой части// } while(Math.abs(difference) > eps); //Конечный критерий, при котором цикл останавливается// //Вывод окончательных результатов на экран// System.out.printf("Левая часть равна = " + left + "\nПравая часть равна = " + right + " \n"); System.out.printf("После n=" + n + " исследуемое выражение отличается от левой части менее, чем на " + Math.abs(eps) + ", а именно на " + Math.abs(difference)); } else{ //Вывод оповещения о неправильном вводе данных (при несоответствии начальному критерию).// if (Math.abs(eps) == 0) System.out.printf("Погрешность равна 0, тогда правая часть стремится к левой" + left + "(n=infinity)"); } } } |
Опять я дал две одинаковые задачи….
Ну, пусть так и будет.
— Не нужно использовать функцию степень. для возведения в квадрат (стр. 14).
Исправил
Принято.
Хорошее решение, корректно переведено на Java, но есть замечания (во многом касается и исходной версии):
Очень неудачный выбор для названия переменной E! Особенно в Java. Оно начинает путаться с Math.E, так же не забывайте, что обычно названия переменных начинаются с маленьких букв. Да и не логичное название. Назовите ее eps, или epsilon, или accuracy .
Также, в условие dife > Math.abs(E) закралась ошибка — и ее пока никто не заметил( ни Игорь Евгеньевич, ни Вы)! Разность (кстати, имя difference будет куда лучше) должна быть по модулю меньше точности вычисления. Опять же сложно найти ошибку, она не бросается в глаза, а почему? Всего лишь, из-за неудачных названий переменных.
Раз уже о стиле зашла речь, то пожалуй, рановато описаны double dife, left, right = 0.0, u = 1.0 ; int n = 0; — они относятся к процессу вычисления, поэтому по логике должны быть описаны уже после ввода исходных данных (кстати, u тоже неудачное имя, по большому счету).
В общем, программа работает, ошибка в коде только одна ( dife > Math.abs(E)), но я пытаюсь научить Вас и нормальному стилю записи программы, поэтому прошу учесть замечания.
Ой, только посмотрел Ваши тесты и описание: вы берете отрицательную погрешность: -0.000545. Это очень необычно. Тогда я понимаю Вашу запись dife > Math.abs(E) . Особенно, если учесть, что левая часть по идее всегда больше, т.к. правая часть монотонно возрастает. Очень странный и нетривиальный момент получился. По классике, разница по модулю меньше погрешности — вот условие останова.
Переименовал переменные и исправил ошибки