Вопрос

Я пишу программу на Python, и мне нужно найти производную от функции (функции, выраженной в виде строки).

  • Например: x^2+3*x
  • Его производным является: 2*x+3

Есть ли какие-нибудь доступные скрипты или вы можете рассказать мне что-нибудь полезное?

Это было полезно?

Решение

симпатия делает это хорошо.

Другие советы

Если вы ограничены полиномами (что, по-видимому, так и есть), в основном будет три шага:

  1. Разобрать входную строку в список коэффициентов до x^n
  2. Возьмите этот список коэффициентов и преобразуйте его в новый список коэффициентов в соответствии с правилами получения полинома.
  3. Возьмите список коэффициентов производной и создайте красивую строку, описывающую производную полиномиальную функцию.

Если вам нужно обрабатывать полиномы, такие как a*x^15125 + x^2 + c, используя dict список коэффициентов может иметь смысл, но требует немного большего внимания при выполнении итераций по этому списку.

Вы можете найти то, что ищете, в уже предоставленных ответах.Однако я хотел бы дать краткое объяснение того, как вычислять символьные производные.

Бизнес основан на перегрузке операторов и правиле цепочки деривативов.Например, производная от v^n является n*v^(n-1)dv/dx, верно?Итак, если у вас есть v=3*x и n=3, какой будет производная?Ответ:если f(x)=(3*x)^3, то производная:

f'(x)=3*(3*x)^2*(d/dx(3*x))=3*(3*x)^2*(3)=3^4*x^2

Правило цепочки позволяет «связать» операцию:каждая отдельная производная проста, и вы просто «связываете» сложность.Другой пример: производная u*v является v*du/dx+u*dv/dx, верно?Если вы получаете сложную функцию, вы просто связываете ее, скажем:

d/dx(x^3*sin(x))
u=x^3; v=sin(x)
du/dx=3*x^2; dv/dx=cos(x)
d/dx=v*du+u*dv

Как видите, дифференцирование — это всего лишь цепочка простых операций.

Теперь перегрузка операторов.

Если вы можете написать парсер (попробуйте Pyparsing), вы можете запросить его для оценки как функции, так и производной!Я сделал это (используя Flex/Bison) просто для развлечения, и это довольно мощно.Чтобы вы поняли, производная вычисляется рекурсивно путем перегрузки соответствующего оператора и рекурсивного применения правила цепочки, поэтому вычисление "*" будет соответствовать u*v для значения функции и u*der(v)+v*der(u) для производного значения (попробуйте на C++, это тоже весело).

Итак, я знаю, что вы не собираетесь писать свой собственный синтаксический анализатор — во что бы то ни стало используйте существующий код (посетите сайт www.autodiff.org для автоматического различения кода Fortran и C/C++).Но всегда интересно узнать, как эта штука работает.

Ваше здоровье,

Хуан

Символическая дифференциация это впечатляющее введение в предмет - по крайней мере, для неспециалиста вроде меня :) Кстати, код написан на C++.

Лучше поздно, чем никогда?

Я всегда проводил символьную дифференциацию на любом языке, работая с деревом синтаксического анализа.Но недавно мне также стало известно о другом методе, использующем комплексные числа.

Подход к дереву синтаксического анализа состоит в переводе следующего крошечного кода Lisp на любой язык, который вам нравится:

(defun diff (s x)(cond
  ((eq s x) 1)
  ((atom s) 0)
  ((or (eq (car s) '+)(eq (car s) '-))(list (car s)
    (diff (cadr s) x)
    (diff (caddr s) x)
    ))
  ; ... and so on for multiplication, division, and basic functions
  ))

и после этого добавляйте соответствующий упрощитель, чтобы вы избавились от сложения 0, умножения на 1 и т.д.

Но сложный метод, хотя и полностью числовой, обладает определенным магическим качеством.Вместо того чтобы программировать свое вычисление F с двойной точностью, сделайте это в комплексе двойной точности.Затем, если вам нужна производная вычисления по переменной X, установите для мнимой части X значение очень малого числа h, например 1e-100.Затем выполните вычисление и получите результат R.Теперь real (R) - это результат, который вы обычно получаете, и imag (R) / h = dF / dX с очень высокой точностью!

Как это работает?Возьмем случай умножения комплексных чисел:

(a+bi)(c+di) = ac + i(ad+bc) - bd

Теперь предположим, что все мнимые части равны нулю, за исключением того, что нам нужна производная по отношению к a.Мы устанавливаем b до очень небольшого числа h.Итак, что мы получаем?

(a+hi)(c) = ac + hci

Итак, реальная часть этого заключается в ac, как и следовало ожидать, и мнимая часть, разделенная на h, является c, которая является производной от ac в отношении a.

Такого же рода рассуждения, по-видимому, применимы ко всем правилам дифференцирования.

Если вы думаете о написании программы дифференцирования с нуля, не используя в качестве помощи другие библиотеки, то алгоритм/подход вычисления производной любого алгебраического уравнения, который я описал в мой блог будет полезно.

Вы можете попробовать создать класс, который будет строго представлять предел, а затем оценить его для (f(x)-f(a))/(x-a), когда x приближается к a.Это должно дать довольно точное значение предела.

Если только любая уже созданная библиотека не является производной, это довольно сложно, потому что вам нужно анализировать и обрабатывать функции и выражения.

Выведение само по себе является простой задачей, поскольку оно механическое и может быть выполнено алгоритмически, но вам нужна базовая структура для хранения функции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top