Вычислить производную с использованием дискретных методов - PullRequest
10 голосов
/ 09 марта 2009

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

Ответы [ 10 ]

10 голосов
/ 11 марта 2009

Я думаю, что вы ищете производную, рассчитанную в точке. Если это так, то здесь есть простой способ сделать это. Вам нужно знать производную в точке, скажем a . Дается пределом разностного отношения для h-> 0:

difference quotient

Вам действительно нужно реализовать функцию предела. Итак, вы:

  • Определите эпсилон, сделайте его меньше, чтобы быть более точным, больше, чтобы быть быстрее
  • Рассчитайте коэффициент разности в начальном h, предположим, что h = 0,01, сохраните его в f1
  • Теперь в цикле DO-WHILE:

    1 - разделите h на 2 (или на 10, важно сделать его меньше)
    2 - снова вычислите коэффициент разности с новым значением h, сохраните его в f2
    3 набора diff = abs (f2-f1)
    4- назначить f1 = f2
    5 - повторить с точки 1 while (diff> epsilon)

  • Наконец, вы можете вернуть f1 (или f2) как значение вашего f '(a)

Помните: Вы предполагаете, что функция дифференцируема в a . Каждый результат, который вы получите, будет неправильным из-за ошибок конечного десятичного знака, которые ваш компьютер может обработать, от этого никуда не деться.

Пример на python:

def derive(f, a, h=0.01, epsilon = 1e-7):
    f1 = (f(a+h)-f(a))/h
    while True: # DO-WHILE
        h /= 2.
        f2 = (f(a+h)-f(a))/h
        diff = abs(f2-f1)
        f1 = f2
        if diff<epsilon: break
    return f2

print "derivatives in x=0"
print "x^2: \t\t %.6f" % derive(lambda x: x**2,0)
print "x:\t\t %.6f" % derive(lambda x: x,0)
print "(x-1)^2:\t %.6f" % derive(lambda x: (x-1)**2,0)

print "\n\nReal values:"
print derive(lambda x: x**2,0)
print derive(lambda x: x,0)
print derive(lambda x: (x-1)**2,0)

Выход:

derivatives in x=0
x^2:         0.000000
x:       1.000000
(x-1)^2:     -2.000000


Real values:
7.62939453125e-08
1.0
-1.99999992328

В первый раз, когда я получил "точное" значение "из-за использования только первых 6 цифр результата, обратите внимание, что я использовал 1e-7 в качестве эпсилона. После этого печатаются РЕАЛЬНЫЕ вычисленные значения, и они, очевидно, математически неправильно. Выбор размера эпсилона зависит от того, насколько точными должны быть ваши результаты.

7 голосов
/ 09 марта 2009

Существует довольно много теории (и установившейся практики) для вычисления числовых ("конечных") производных. Получение всех деталей правильно, так что вы верите результат, не тривиально. Если есть какой-либо способ, вы можете получить аналитическую производную функции (используя ручку и бумагу, или систему компьютерной алгебры, такую ​​как Maple , Mathematica , Sage , или SymPy ), на данный момент это лучший вариант.

Если вы не можете получить аналитическую форму или вы не знаете функцию (только ее вывод), тогда численная оценка - ваш единственный вариант. Эта глава в Числовых рецептах в Си - хорошее начало.

4 голосов
/ 09 марта 2009

Простой метод состоит в том, чтобы вычислить изменение f по небольшому значению для каждой точки производной, которая вас интересует. Например, чтобы вычислить ∂f / ∂x, вы можете использовать это:

epsilon = 1e-8
∂f/∂x(x, y, z) = (f(x+epsilon,y,z) - f(x-epsilon, y, z))/(epsilon * 2);

Остальные части будут похожи по y и z.

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

3 голосов
/ 12 марта 2009

Чтобы провести численное дифференцирование, которое всегда является приближенным, существует два распространенных сценария:

  1. У вас есть способ (алгоритм, уравнение) для вычисления значения f (x) при любом заданном x или
  2. У вас есть значение f (x) при наборе равных интервалов значений x (f (1), f (1.5), f (2) и т. Д.):


  1. Если у вас есть алгоритм, то вам лучше всего посмотреть Ответ Андреа Амбу *:
    1. Начните со значений f (a + h) и f (a-h) и выполните
      f '(a) = {f (a + h) -f (a-h)} / 2ч
      Это называется центральной разницей.
    2. Уменьшайте размер смещения h, пока f '(a) не перестанет меняться, согласно ответу Андреа.
    • Будьте осторожны, чтобы не делить на 2 часа, не проверяя, что оно больше 0, иначе вы получите деление на ноль ошибок.
  2. Если у вас есть значение функции при наборе значений f (x) = f (x n ) = f n , то мы можем сделать что-то похожее на вышеупомянутый метод, но наша точность будет ограничена значениями x n и промежутками между ними.
  3. Первое приближение состоит в том, чтобы просто использовать тот же оператор центральной разности, что и выше;
    f ' n = (f n + 1 - f n-1 ) / 2 ч,
    где h - равный интервал между значениями x n .
  4. Далее следует использовать трафарет из пяти пунктов , хотя он имеет только 4 коэффициента, как подробно описано на этой странице википедии. При этом используются значения от f n-2 до f n + 2 : f ' n = (-f n + 2 + 8f n + 1 - 8f n-1 + f n-2 ) / 12 ч.
  5. Существуют аппроксимации более высокого порядка, использующие больше точек, но их становится все труднее вычислять для уменьшения отдачи, и они становятся более нестабильными в численном выражении.
  6. ** Примечание **: эти формулы для конечных разностей основаны на том, что f приблизительно равна форме многочлена в диапазоне x n-1 & le; x & le; n + 1 . Для таких функций, как синусоидальные волны, они могут быть очень плохими при вычислении производной с хорошей степенью точности.

* Ответ Андреа использует прямой разностный оператор {f (a + h) - f (a)} / h вместо центрального разностного оператора {f (a + h) - f (ah)} / 2h, но оператор прямой разницы менее точен в численных решениях.

2 голосов
/ 01 августа 2009

Автоматическое дифференцирование - это самый точный и концептуально удивительный способ делать подобные вещи. Просто немного сложнее.

2 голосов
/ 09 марта 2009

Если не использовать символический математический язык, такой как Maple, лучшее, что вы можете сделать, - это аппроксимировать производную в различных точках. (И затем интерполируйте, если вам нужна функция.)

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

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

1 голос
/ 09 марта 2009

Формально нет. Либо вы описываете (частичные) производные дискретных функций, либо вы запрашиваете численный метод для аппроксимации (частичных) производных непрерывных функций.

Дискретные функции не имеют производных. Если вы просмотрите определение производной эпсилон-дельта, вы увидите, что вам нужно будет иметь возможность оценить функцию, близкую к точке, в которой вы хотите получить производную. Это не имеет смысла, если функция имеет значения только при целочисленных значениях x, y и z. Таким образом, нет способа найти производную дискретной функции для любого значения fast.

Если вы хотите, чтобы численный метод точно вычислял производные непрерывной функции, вам тоже не повезло. Численные методы для производных являются эвристическими, а не алгоритмическими. Не существует численного метода, который гарантировал бы точное решение. К счастью, существует много хороших эвристик. Mathematica использует специализированную версию метода основных осей Брента по умолчанию. Я бы порекомендовал вам использовать Научную библиотеку GNU , которая имеет очень хорошую реализацию метода Брента. Вся моя оценка на одном из моих курсов по математике обязана GSL. Рубиновые крепления довольно хороши, если это ваша вещь. При необходимости большинство библиотек числового дифференцирования имеют несколько доступных методов.

Если вы действительно хотите, я могу достать пример кода. Дайте мне знать.

0 голосов
/ 11 марта 2009

Я надеюсь, что это может быть полезно ЧИСЛЕННАЯ ДИФФЕРЕНЦИАЦИЯ.

0 голосов
/ 09 марта 2009

Если функция линейная, как вы указали, то производные тривиальны. Производная по «х» - это «а»; производная по «у» - это «b», а производная по «z» - «с». Если уравнение имеет более сложную форму и вам нужна формула, представляющая решение, а не эмпирическое решение, пожалуйста, отправьте более сложную форму уравнения.

Привет

0 голосов
/ 09 марта 2009

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

Когда вы используете слово «дискретный», это заставляет меня думать, что вам нужны «конечные различия». Для расчета аппроксимации вам потребуется некоторая дискретизация.

Df / Dx ~ (f2-f1) / (x2-x1) и т. Д.

...