Задача: В задаче задана функция и её разложение в ряд или произведение. Численно убедится в справедливости равенства, для чего для заданного значения аргумента [latex] x [/latex] вычислить левую его часть и разложение, стоящее в правой части, с заданной погрешностью [latex]\varepsilon\[/latex]. Испытать разложение на сходимость при разных значениях аргумента, оценить скорость сходимости, для чего вывести число итераций [latex] n [/latex] (слагаемых или сомножателей), необходимых для достижения заданной точности.
[latex]\sin \left(x \right) = x \left(1 — \frac{x^{2}}{\pi^{2}} \right) \left( 1 — \frac{x^{2}}{4\pi^{2}} \right) \ldots \left(1 — \frac{x^{2}}{ \left( n-1 \right)^{2}\pi^{2}} \right)[/latex]
Тесты:
x | n-Excel | sin — Excel | deviation — Excel | e — input | exact sinus | n — program | deviation — program |
12 | 22 | -1,029367 | 0.56 | 0.56 | -0.536573 | 22 | 0.524789 |
5 | 7 | -1,346966 |
0.54 | 0.54 | -0.958924 | 7 | 0.461469 |
2.5 | 2 | 0,771704 | -1.15 | -1.15 | 0.598472 | 2 | -0.318384 |
1 | 2 | 0,875915 | -1.38 | -1.38 | 0.841471 | 2 | -0.057208 |
0 | 2 | 0 | -0.53 | -0.53 | 0 | 2 | 0 |
-1 | 2 | -0,875915 | 0.3 | 0.3 | -0.841471 | 2 | 0.057208 |
-2.5 | 6 | -0,659746 | 0.08 | 0.08 | -0.598472 | 6 | 0.073087 |
-5 | 4 | 1,700161 | -1.62 | -1.62 | 0.958924 | 4 | -1.061024 |
-12 | 12 | 1,755690 | -1.63 | -1.63 | 0.536573 | 12 | -1.417062 |
Код программы:
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 |
#include <stdio.h> #include <math.h> double pow2( double x ) //вторая степень { return x*x; } int main() { // рабочие переменные double x, e, d, r; unsigned int n, nMax = 0xffffffff; // лимит числа итераций чтобы избежать бесконечного цикла // ввод данных - аргумента функции и заданной погрешности scanf("%lf", &x); scanf("%lf", &e); for( r = x, n = 2; n < nMax; n++ ) // основной цикл вычислений { r = r * ( 1 - pow2( x ) / ( pow2( n - 1 ) * pow2( M_PI ) ) ); d = sin( x ) - r ; if( fabs( d ) <= fabs( e ) ) break; } // вывод результата printf("sin(x) = %lf\n", sin( x ) ); printf("calculated sinus = %lf\n", r ); printf("inaccuracy = %lf\n", d ); printf("number of iterations: %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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import java.util.*; import java.lang.*; import java.io.*; class SinusApp { public static Double scanDouble( Scanner in ) { return ( ( in.hasNextDouble() ) ? in.nextDouble() : null ); } public static double pow2( double x ) //вторая степень { return x*x; } public static void main( String[] args ) { // рабочие переменные double x, e, d, r; long n, nMax = Long.MAX_VALUE; // лимит числа итераций чтобы избежать бесконечного цикла // ввод данных - аргумента функции и заданной погрешности Scanner in = new Scanner(System.in); x = scanDouble( in ); e = scanDouble( in ); in.close(); for( d = 0, r = x, n = 2; n < nMax; n++ ) // основной цикл вычислений { r = r * ( 1 - pow2( x ) / ( pow2( n - 1 ) * pow2( Math.PI ) ) ); d = Math.sin( x ) - r ; if( Math.abs( d ) <= Math.abs( e ) ) break; } // вывод результата System.out.printf("sin(x) = %f\n", Math.sin( x ) ); System.out.printf("calculated sinus = %f\n", r ); System.out.printf("inaccuracy = %f\n", d ); System.out.printf("number of iterations: %d\n", n ); } } |
Ссылка:http://ideone.com/nZluY8
Программа состоит из следующих частей:
- Определение вспомогательной функции
- Рабочие переменные
- Определяем лимит числа итераций чтобы избежать бесконечного цикла
- Ввод данных — аргумента функции и заданной погрешности
- Условие выполнения
- Вывод результата
Правильность результата проверялась на калькуляторе. тестирование показало, что правильные значения получаются только при очень большом n . Только начиная с десятков тысяч результат близок к показанию калькулятора.
Данные для проверки подготавливались в Excel ввиду относительно большого количества итераций, необходимых для расчётов. Полученная погрешность с точным значением синуса использовались как входное [latex]e[/latex]. Результирующее количество итераций программы сравнивалось с числом итераций, сделанных в Excel. Ввиду того, что double намного точнее чем значения в Excel, возможны различия в числе итераций ( назначенных ).
Ссылка на ideone.com: http://ideone.com/fork/Wh91nH
— \varepsilon Вы вставили без тегов.
— К чему в условии слово «Решить»? Ненужно оно там.
— Метки
— Вы неправильно поняли условие. Нужно не повторять n-раз. Нужно повторять до тех пор пока разность между левой и правой частью больше эпсилон. И подсчитать каким окажется n.
Задачу переделал, ожидаю проверки.
По программе:
— есть готовая функция fabs() для вычисления модуля, но можно и так как у Вас,
— сейчас работает правильно, но очень не эффективно. Вы берёте некоторое n и вычисляете произведение n сомножителей. Если точность не достигнута, то это произведение отбрасывается и вычисляется произведение n+1 сомножителя. Т.е. вместо ещё одного умножения Вы снова делаете n умножений, а потом ещё одно. В результате сложность алгоритма растёт как n2 вместо линейной. Я бы посоветовал передавать в функцию calcSin() требуемую точность и заменить в ней условие выхода из цикла на достижение точности. Число n (количество шагов) можно возвращать как результат (это в задаче и спрашивают), поскольку само значение синуса в этой задаче интереса не представляет.
По оформлению:
— «По этому тестирование выполнялось при n = 1000000» — это видимо фраза из старого отчёта. Теперь значения n указаны в таблице для разных значений точности и можно эту фразу убрать. То что сходимость происходит медленно Вы указали вполне справедливо;
— удалите пустые строки в тексте;
— пробелы ставят с наружной части скобок, а не с внутренней. Иначе получается как у Вас — открывающая скобка остаётся на предыдущей строке или наоборот — закрывающая переносится на новую строку. Такое форматирование не логично и считается признаком непрофессиональной работы. Это касается только текста отчёта.
— в метках написано «разложение в ряд». Это не ряд. Исправьте, пожалуйста. И не нужно соединять метки союзом и. Система требует вводить по одной или через запятую.
Нет. Так не годится. От того, что Вы начали с n=10 и стали увеличивать на 10 ничего не изменилось к лучшему. Нужно сделать так, как написано в предыдущем комментарии.
Еще одно серьезное замечание.
Нельзя выдавать за тесты результаты работы своей (неправильной) программы. Тесты должны быть вычислены ДРУГИМ способом.
Ровно половина Ваших тестов полная чушь. Вы вычисляете значение синуса с точностью 3, 5, 11, 12. Это абсолютная бессмыслица. Ещё и на это требуется 10 шагов по Вашим тестам.
Принято
Засчитана Java версия. (какой тонкий момент с d = 0 ! по мнению Java компилятора, цикл for, как цикл с предусловием, может не выполнится ни разу… и тогда d не будет инициировано, если не написать эту вроде лишнюю конструкцию d = 0 )