Изчисляване на производни с C шаблони

Вдъхновен от пост. По пътя получихме нещо подобно на нашата собствена реализация на ламбда изрази :) С възможност за изчисляване на производната на етапа на компилация. За да дефинирате функция, можете да използвате операторите +, -, *, /, както и редица стандартни математически функции. Sqr - повдигане на квадрат Sqrt - квадратен корен Pow - реална степен Exp - експоненциална Log - логаритъм Sin, Cos, Tg, Ctg, Asin, Acos, Atg, Actg - тригонометрия

Производната се изчислява с помощта на функцията за производна. Има функтор на входа и същият на изхода. За да може производната да бъде изчислена точно, входът трябва да бъде функтор, определен с помощта на специален синтаксис. Синтаксисът е интуитивен (поне се надявам). Ако входът за производна е друг функтор или ламбда с подходяща сигнатура (double -> double), тогава производната ще бъде изчислена приблизително. Пример:

Работи така:

Файлът CrazyMath.h се оказа доста голям, така че няма смисъл да го включвате изцяло в статията. Тези, които се интересуват, могат да изтеглят изходния код от Github

UPDДобавен е метод на израз и typedef, съответстващ на типа, който методът на израз връща към класа Derivative. Методът на израза връща функтор, подходящ за по-нататъшно диференциране. Въпреки това, когато се изчисляват производни от 2-ри, 3-ти и по-високи разряди, размерът на израза нараства бързо, така че компилирането може да отнеме повече време.

Hardcore conf в C++. Каним само професионалисти.

Чете сега

Различни шаблони. Кортежи, разопаковане и други

Номериране на променливи шаблонни аргументи или какво крие скромна двойка

Работа с jQueryШаблони

Коментари 22

Като първо приближение ще се справи добре. Освен това, това е просто мъниче.

Операцията на численото диференциране не е стабилна, за разлика от численото интегриране. С прости думи, при интегриране гладкостта на функция се увеличава, а при диференциране намалява.

Затова предлагам следния трик, който разбира се не решава проблема, но ви позволява да се справите по-добре с него в някои случаи. Изчислете производната чрез интеграла

Като вземем например трапецовидния метод за числено интегриране, получаваме разликата

Което дава n-2 линейни уравнения за i=2..n-1. Като добавим към него според състоянието на краищата, получаваме затворена система, която може да бъде решена чрез метода на почистване. Ако има проблеми при решаването на линейна система, тогава в този случай трябва да се използват други методи и / или допускания.

PS. Тук u_x и u са свързани само чрез интегрални отношения, т.е. u_x формално не е производна на u по отношение на x. Това е дискретна функция, свързана с друга дискретна функция u чрез определена зависимост. Обозначенията са избрани само за удобство.

1. Изчислете производната на abs(x) при x=0. Тъй като нямате шаблон за него, той ще бъде изчислен числено.

2. Изчисляването на стойността на полином в точка за операции с плаваща запетая също е нестабилно. Въпреки че производната се изчислява лесно като аналитичен израз, изчисляването на стойността на производната за конкретен x може вече при степени > 20 могат да се различават на порядък.

3. Не видях система за опростяване на изрази във вашата система. Тези. могат да възникнат много лоши изрази за операции с плаваща запетая като 0 - 0. Нарушаване на асоциативността на операциите за събиране (или изваждане) поради закръгляване. Често (a + b)+ c != a + (b + c) следователно „правилното“ пренаписване на формулите, по които броите, може да помогне. С умножението всичко е тип-топ. Разбирам, че всеки има математически анализ в главата, но трябва да има алгебра. Но това е исторически дефект в нашето математическо образование.

Прочетете Кнут "Изкуството на програмирането" v.2 "Изведени алгоритми".

4. Всичко, което сте направили, не е лошо, но ако го направите правилно математически, получавате малка система за компютърна алгебра. Спомням си, че с някакъв вид пролог беше даден пример за аналитично диференциране на функции. Буквално няколко реда, но след това огромен код, който просто да опрости получения израз. В същото време той често не работи правилно. Тъй като има цял набор от теореми, че за някои типове изрази няма канонично представяне и дори няма алгоритъм за нормална форма.

5. Следователно, въпреки всички недостатъци на операциите с плаваща запетая, все още е по-лесно и по-добре за C ++ да избере числовата опция.