Страницы

Поиск по вопросам

понедельник, 25 февраля 2019 г.

Разложение подынтегральной функции с помощью формулы Эйлера

Решение интеграла в преобразовании Фурье
Численным методам этот интеграл не решить из за наличия комплексной мнимой единицы,порекомендовали Формула Эйлера с разложением подынтегральной функции на косинус и синус
Вопрос возник с применением Формулы Эйлера
Получается нужно вручную разделить формулу на 2 части присвоить согласно формуле Эйлера каждую часть к интегралу. Или существует другой вариант?
public void frmEiler(int U,int T) { double x1=0,x2=0; ///U*Math.Exp(-j * w * t) dt///формула double j = Math.Sqrt(-1);// мнимая единица double f = 0,w = 0; int t = 1; f = 1 / T; w = 2 * Math.PI * f; Math.Exp(-j * w * t) =U* Math.Cos(w * t) + j * Math.Sin(t); x1=Math.Cos(w * t); x2=j * Math.Sin(t); }
public double func1(double x1) { ///1-ая часть подыинтегральной функции return; }
public double func2(double x2) { ///2-ая часть подыинтегральной функции return; }


Ответ

Скорее всего с помощью формулы Эйлера Вы решили избавиться от мнимой единицы, чтобы вычислить численно интегралы. Я в математике не силен, не знаю верно ли, но решил попробовать.
Получается нужно вручную разделить формулу на 2 части присвоить согласно формуле Эйлера каждую часть к интегралу
По формуле Эйлера нужно вычислить интеграл sin'а и интеграл cos'а. Дальше из полученных результатов получить комплексное число.
Что я делал
Я создал класс NumericalIntegration, который интегрирует функцию с помощью Численного интегрирования. Т.к. существует несколько методов решения (я буду называть их способы, чтобы не путать с термином метод в программировании), поэтому я решил создать интерфейс, который будет подразумевать какой-то способ решения. А реализация этого интерфейса уже будет конкретным способом решения. Я так сделал, чтобы при разработки можно было добавить еще какие-то способы решения.
interface NumericalIntegrationRule { double Calculate(Func func, double min, double max, double subintervalsCount); }
У способа решения должен быть метод, который принимает функцию func, отрезок интегрирования [min,max] и число подинтервалов n, т.е. насколько частей делим отрезок, чем больше отрезков, тем больше точность интегрирования. Конечно же, лучше было бы сделать погрешность, но я по-быстрому заложился на количество отрезков. Можете сами потом изменить это.
А в классе интегрирования NumericalIntegration уже будет вызов нужного способа решения. Нужный способ передается через конструктор. Плюс добавил параметры по умолчанию: число отрезков.
class NumericalIntegration { public readonly NumericalIntegrationRule DefaultRule = null; public readonly int DefaultSubintervalsCount = 100000;
public NumericalIntegration() { DefaultRule = new TrapezoidalRule(); }
public NumericalIntegration(NumericalIntegrationRule defaultRule) { DefaultRule = defaultRule; }
public NumericalIntegration(NumericalIntegrationRule defaultRule, int defaultSubintervalsCount) : this(defaultRule) { DefaultSubintervalsCount = defaultSubintervalsCount; }
public double Calculate(NumericalIntegrationRule rule, Func func, double min, double max, double subintervalsCount) { return rule.Calculate(func, min, max, subintervalsCount); }
public double Calculate(Func func, double min, double max) { return Calculate(DefaultRule, func, min, max, DefaultSubintervalsCount); } }
Я реализовал только метод трапеций:
class TrapezoidalRule : NumericalIntegrationRule { public double Calculate(Func func, double min, double max, double subintervalsCount) { double result = 0; double step = (max - min) / subintervalsCount;
for (double i = min; i < max; i += step) result += ((func(i) + func(i + step)) / 2) * step;
return result; } }
А можно было бы на каждый способ решения в классе NumericalIntegration создать отдельный метод этого CalculateWithTrapezoidalRule, CalculateWithRectangleRule и т.д.
Теперь у нас есть классы для численного интегрирования. Можно их использовать для нахождения спектральной плотности. Я не в курсе как у Вас устроена система, поэтому я работал в консольном приложении и в этом приложении вынес расчет плотности в отдельный статический метод:
static Complex GetSpectralDensity(double amplitude, double frequency, double time) { NumericalIntegration integration = new NumericalIntegration(); double real = amplitude * integration.Calculate(x => Math.Cos(-frequency * x), 0, time); double imaginary = amplitude * integration.Calculate(x => Math.Sin(-frequency * x), 0, time); return new Complex(real, imaginary); }
Все как в формуле Эйлера: интегрируются обе части, а потом на основе их результатов создается комплексное число, которое и будет равно значения плотности.
Дальше, решил проверить результаты моей программы с результатами Mathcad. Mathcad, вроде бы, говорит, что результаты, вычисленные после преобразования по формуле Эйлера, будут такие же, как и результаты, полученные без преобразования. Проверил на этих же данных и свою программу.
static void Main(string[] args) { double amplitude = 25; double time = 50;
for (int frequency = -100, counter = 0; frequency <= 100; frequency++, counter++) Console.WriteLine("{0}: {1}", counter, GetSpectralDensity(amplitude, frequency, time).ToString()); }

Вроде бы, похоже. Попробуйте реализовать другие способы решения и вычислить с помощью их.
Забыл сказать, что я использовал сборку System.Numerics.dll для представления комплексного числа. Надеюсь, ее то можно использовать :)

Комментариев нет:

Отправить комментарий