Задача: Периодические функции. Утверждается, что функция [latex]y = f\left ( x \right)[/latex] периодическая с периодом [latex]T[/latex]. Проверить это численно, вычислив функцию с постоянным шагом на отрезке [latex]\left [ 0,5T \right ][/latex]. Учесть погрешность вычислений и возможные точки разрыва функции. Проверить на примере функций:
[latex]y=\sin^{2}x[/latex], [latex]y=\tan x[/latex] [latex]\left (T=\pi\right)[/latex];
[latex]y=\frac{1}{x}\cdot \sin x[/latex] [latex]\left (T=2\pi\right)[/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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#include <iostream> #include <math.h> using namespace std; enum FUNCTION_TYPE { FUNC_TAN,FUNC_SIN2,FUNC_SIN_X }; const double kFault = 0.001; const int kPeriodNum = 5; bool check_periodic(double step,double T, FUNCTION_TYPE func_type); bool is_periodic(double f_x, double f_nx); bool is_point_gap(double x, FUNCTION_TYPE func_type); double calc_function(double x, FUNCTION_TYPE func_type); void print_functions(double f_x, double f_nx,int n, FUNCTION_TYPE func_type); int main() { cout << (check_periodic(M_PI_4,M_PI,FUNC_TAN) ? "tan(x) periodic" : "tan(x) not periodic") << endl; cout << "------------------------" << endl; cout << (check_periodic(M_PI_4,M_PI,FUNC_SIN2) ? "sin(x)^2 periodic" : "sin(x)^2 not periodic") << endl; cout << "------------------------" << endl; cout << (check_periodic(M_PI_4,2*M_PI,FUNC_SIN_X) ? "sin(x)/x periodic" : "sin(x)/x not periodic") << endl; } bool check_periodic(double step,double T, FUNCTION_TYPE func_type) { int number_steps = T/step; double x = 0, f_x = 0, f_nx = 0; bool periodic = true; for (int i = 1; i != number_steps; i ++) { x = i*step; cout << "x = " << x << endl; if (is_point_gap(x,func_type)) { cout << "Function has undefined value" << endl; continue; } f_x = calc_function(x, func_type); for (int j = 1; j < kPeriodNum; j ++) { f_nx = calc_function(x + j*T, func_type); print_functions(f_x, f_nx, j, func_type); if (is_periodic(f_x,f_nx) == false) { return false; } } } return periodic; } void print_functions(double f_x, double f_nx, int n, FUNCTION_TYPE func_type) { if (func_type == FUNC_TAN) { cout << "tan(x) = " << f_x << " | tan(x +" << n << "T) = " << f_nx << endl; } else if (func_type == FUNC_SIN2) { cout << "sin(x)^2 = " << f_x << " | sin(x + " << n << "T)^2 = " << f_nx << endl; } else if (func_type == FUNC_SIN_X){ cout << "sin(x)/x = " << f_x << " | sin(x + " << n << "T)/(x + " << n << "T) = " << f_nx << endl; } } double calc_function(double x, FUNCTION_TYPE func_type) { if (func_type == FUNC_TAN) { return tan(x); } else if (func_type == FUNC_SIN2) { return sin(x)*sin(x); } else if (func_type == FUNC_SIN_X){ return sin(x)/x; } } bool is_point_gap(double x, FUNCTION_TYPE func_type) { if (func_type == FUNC_TAN) { return (x == M_PI_2); } else if (func_type == FUNC_SIN_X) { return (x == 0); } else if (func_type == FUNC_SIN2){ return false; } } bool is_periodic(double f_x, double f_nx) { return (fabs(f_x) - fabs(f_nx)) < kFault; } |
Результаты:
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 |
x = 0.785398 tan(x) = 1 | tan(x +1T) = 1 tan(x) = 1 | tan(x +2T) = 1 tan(x) = 1 | tan(x +3T) = 1 tan(x) = 1 | tan(x +4T) = 1 x = 1.5708 Function has undefined value x = 2.35619 tan(x) = -1 | tan(x +1T) = -1 tan(x) = -1 | tan(x +2T) = -1 tan(x) = -1 | tan(x +3T) = -1 tan(x) = -1 | tan(x +4T) = -1 tan(x) periodic ------------------------ x = 0.785398 sin(x)^2 = 0.5 | sin(x + 1T)^2 = 0.5 sin(x)^2 = 0.5 | sin(x + 2T)^2 = 0.5 sin(x)^2 = 0.5 | sin(x + 3T)^2 = 0.5 sin(x)^2 = 0.5 | sin(x + 4T)^2 = 0.5 x = 1.5708 sin(x)^2 = 1 | sin(x + 1T)^2 = 1 sin(x)^2 = 1 | sin(x + 2T)^2 = 1 sin(x)^2 = 1 | sin(x + 3T)^2 = 1 sin(x)^2 = 1 | sin(x + 4T)^2 = 1 x = 2.35619 sin(x)^2 = 0.5 | sin(x + 1T)^2 = 0.5 sin(x)^2 = 0.5 | sin(x + 2T)^2 = 0.5 sin(x)^2 = 0.5 | sin(x + 3T)^2 = 0.5 sin(x)^2 = 0.5 | sin(x + 4T)^2 = 0.5 sin(x)^2 periodic ------------------------ x = 0.785398 sin(x)/x = 0.900316 | sin(x + 1T)/(x + 1T) = 0.100035 sin(x)/x not periodic |
Периодическая функция ― функция, повторяющая свои значения через некоторый регулярный интервал аргумента, то есть не меняющая своего значения при добавлении к аргументу некоторого фиксированного ненулевого числа (периода функции) на всей области определения.
Исходя из определения периодичности функции были получены данные сверху.
Следовательно можно сделать вывод, что функция [latex]y=\tan x[/latex] и функция [latex]y=\sin^{2}x[/latex] периодичны, а функция [latex]y=\frac{1}{x}\cdot \sin x[/latex] не периодична.
Графики подтверждают результаты расчетов:
Ссылка на код.
Решение на 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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
import java.util.*; import java.lang.*; import java.io.*; class Main { enum FUNCTION_TYPE { FUNC_TAN,FUNC_SIN2,FUNC_SIN_X }; static double kFault = 0.001; static int kPeriodNum = 5; public static void main (String[] args) { if ( check_periodic(Math.PI/4, Math.PI, FUNCTION_TYPE.FUNC_TAN) ) System.out.println("tan(x) periodic") ; else System.out.println("tan(x) not periodic"); System.out.println("------------------------"); if ( check_periodic(Math.PI/4, Math.PI, FUNCTION_TYPE.FUNC_SIN2) ) System.out.println("sin(x)^2 periodic"); else System.out.println( "sin(x)^2 not periodic") ; if ( check_periodic(Math.PI/4, 2*Math.PI, FUNCTION_TYPE.FUNC_SIN_X) ) System.out.println("sin(x)/x periodic"); System.out.println("sin(x)/x not periodic"); } static boolean check_periodic(double step,double T, FUNCTION_TYPE func_type) { int number_steps = (int) (T/step); double x = 0, f_x = 0, f_nx = 0; boolean periodic = true; for (int i = 1; i != number_steps; i ++) { x = i*step; System.out.println ("x = " + x ); if (is_point_gap(x,func_type)) { System.out.println ("Function has undefined value"); continue; } f_x = calc_function(x, func_type); for (int j = 1; j < kPeriodNum; j ++) { f_nx = calc_function(x + j*T, func_type); print_functions(f_x, f_nx, j, func_type); if (is_periodic(f_x,f_nx) == false) { return false; } } } return periodic; } static void print_functions(double f_x, double f_nx, int n, FUNCTION_TYPE func_type) { if (func_type == FUNCTION_TYPE.FUNC_TAN) { System.out.println ("tan(x) = "+ f_x+ " | tan(x +"+ n +"T) = " +f_nx ); } else if (func_type == FUNCTION_TYPE.FUNC_SIN2) { System.out.println ("sin(x)^2 = "+ f_x+ " | sin(x + "+ n+ "T)^2 = "+ f_nx); } else if (func_type == FUNCTION_TYPE.FUNC_SIN_X){ System.out.println ("sin(x)/x = "+ f_x+ " | sin(x + "+ "T)/(x + " + n + "T) = "+ f_nx); } } static double calc_function(double x, FUNCTION_TYPE func_type) { if (func_type == FUNCTION_TYPE.FUNC_TAN) { return Math.tan(x); } else if (func_type == FUNCTION_TYPE.FUNC_SIN2) { return Math.sin(x)*Math.sin(x); } else if (func_type == FUNCTION_TYPE.FUNC_SIN_X){ return Math.sin(x)/x; } return 0; } static boolean is_point_gap(double x, FUNCTION_TYPE func_type) { if (func_type == FUNCTION_TYPE.FUNC_TAN) return (x == Math.PI/2); else if (func_type == FUNCTION_TYPE.FUNC_SIN_X) return (x == 0); else if (func_type == FUNCTION_TYPE.FUNC_SIN2) return false; return false; } static boolean is_periodic(double f_x, double f_nx) { return (Math.abs(f_x) - Math.abs(f_nx)) < kFault; } } |
— Иллюстрации крошечные, разглядеть ничего нельзя. При вставке на сайт автоматически создаётся изображение небольшого размере по нажатию на которое показывается полный размер. Если переделка займёт много времени, то оставляйте как есть.
— Подписи к рисункам не всегда соответствуют изображению.
— По графику y = sin(x)/x. Wolframalpha может себе позволить нарисовать значение этой функции в точке 0, а Вам такое не простят 🙂
— int VERY_LARGE_NUMBER = 999999999999 выходит за пределы допустимого целого числа. Т.е. Вы задали -727379969. Тем более нет смысла использовать это в функции, которая возвращает double. Если очень хочется вернуть бесконечность, то нужно написать так numeric_limits<double>::infinity( ). Только нужно подключить #include <limits>
— С вычислением тангенса Вы что-то перемудрили. Функция из математической библиотеки отлично справляется с поставленной задачей, а Вашt return atan2(x,0); совсем не то делает.
— Нет выводов о периодичности или не периодичности функций.
— Почему только 5 точек? Сказано «вычислив функцию с постоянным шагом» и задан интервал от нуля до пяти предполагаемых периодов. Не сказано, что 5 точек.
Пяти точек достаточно, чтобы проследить периодичность функции. Могу я оставить такое количество?
Нет, недостаточно. Нет, не можете.
А какое количество точек будет достаточно?
Для доказательства периодичности недостаточно никакого числа точек. Но в задаче требуется не доказать, а проверить численно. Читаем условие «вычислив функцию с постоянным шагом «. Т.е. нужно задать шаг (желательно в долях пи) и проверять совпадение значений функции в точках, отличающихся на период.
Формально, Вы не выполнили условие задачи. Не проверили периодичность и не прошли с постоянным шагом от 0 до 5Т. Понятно почему. Не всякий шаг подойдёт — нужно чтобы период составлял целое число шагов. Иначе нельзя проверить периодичность. Т.е. я готов принять, что Вы с постоянным шагом проходите только период, а остальные точки получаете добавлением одного, двух, трёх и четырёх периодов. Но Вы проходите только часть точек. И даже не печатаете каких именно. Печатаете только значения функций, не указывая от какого аргумента.
И самое главное — Вы ничего не проверяете с учётом погрешности вычислений. Просто печатаете, а проверять будет человек, просматривая результаты.
Попробуем сформулировать (близко к Вашему подходу) то, что нужно делать.
1. Ввести шаг.
2. Ввести допустимую погрешность (величину отклонения значений в пределах которого они считаются одинаковыми).
3. Для каждой из трёх функций выполнить отдельно следующий пункт.
4. Циклически в пределах периода вычислять значения функции в точках х с введенным шагом и сравнивать со значением в точках х+Т, х+2Т, х+3Т, х+4Т. Если значения отличаются более чем на допустимую погрешность то вывести «функция непериодическая» и перейти к следующей функции из п.3.
5. Если цикл п.4 закончился, не обнаружив несовпадения, то вывести «функция периодическая» и перейти к следующей функции из п.3.
Я переписала программу, добавив те пункты, которые вы описали.
(ввела шаг, погрешность, вывод угла и значения функции в разных точках)
Зачтено