Собственно сабж. В гугле находил что-то мутное, и как я понял лучше использовать ПОЛИЗ только префиксный (могу не правильно назвать). Аналитическая запись представляет строку вида "(x+2)^2+3*y" вообще набор операторов "+" "-" "^" (степень, производная от xor тт), еще желательно поддержка "/". Так вот задача вроде не сложная, но все-таки лучше использовать наработанные и проверенные алгоритмы. Предлагайте!
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1327 Используй слово вычисление вместо взятие и гугл тебе поможет.
valterg честно говоря кроме этого примера, там только учебники по Мат Пакетам, но я гляну что за пример, хотя там и богомерзкий делфи
так все просто же, парсишь формулу в дерево, которое есть композиция функций, потом берешь производную по правилам
если использовать 3 правила a + b -> a' + b' a * b -> a'*b + a*b' a^n -> n*a^(n-1) (откуда a/b = a*(b^-1) -> a'/b-a*(b^-2)*b' = (a'*b-a*b')/b^2 ) то и в дереве должны быть операции 3х типов само собой для этого лучше всего подходит ООП, паттерн интерпретатор (см. GoF)
GoldFinch да понятно что просто, просто выбираю оптимальное решение, можно дерево, но я полиз пробовать.
а как входные заданы? как массив выборок через промежутки времени? и нужно получить массив выборок производной? тогда тупо дY(X)/дX а запись в виде строки в не самых сложных случаях вполне можно перевести по правилам, как и писал GoldFinch, с помощью любимого компилера парсеров. а вот ооп в данной задаче требуется как зайцу стоп-сигнал
qqwe Как строка задана, естесно и я прекрасно понимаю как надо решать эту задачу, просто может есть мегоСуперСпособ который я не знаю. не понял, что имеете в виду? конечно тривиальный полиз можно назвать "любимым компилиром" но я не вкурил ) А про хм, вроде слово аналитически противоречит "получить массив выборок" и тогда тупо дY(X)/дX не лучший, а точнее не правильный метод, а так методы численного вычисления производной тоже мне известны. PS ладно, пойду начну писать там видно будет, не если есть мегоСуперСпособ, то сообщите пожалуйста
SPA отвечаете непонятной фразой на непонятную? имелось ввиду, что в любом языке для построения парсеров есть пример разборщика входных формул на примитивы. может, немного модифицировав примеровый разборщик и дописав в него обработчики (добавлятели соотв узла в дерево разбора) вы довольно быстро управитесь. "аналитически" я понимаю как "численно", а формулы это немного не отсюда. хотя может я и ошибаюсь. ЗЫ приведите правильный способ. мне иногда сталкиваться с таким приходится. чтобы знать
совершенно наоборот, численно != аналитически это скорее противоположности. все GoldFinch правильно сказал, для составление дерева юзать ПОЛИЗ вот и все, хотя когда задача будет решена, тогда и можно будет говорить о чем-то.
http://ru.wikipedia.org/wiki/Обратная_польская_запись это? а зачем оно? и читать куда как труднее я имею ввиду. разобрать формулу можно так. (упрощенный вариант. без построения и анализа дерева) # o - словарь вида {'p': "производная", n: "не производная"} # компилятор coco - питон форк (есть форки под достаточный спектр лангов) Код (Text): In<out o> = (. o = '' .) AddSub<out o> . AddSub<out o> = MulDiv<out o1> { ( "+" (. op = "+" .) | "-" (. op = "-" .) ) MulDiv<out o2> (. (o1p, o1n) = (o['p'], o['n']) (o2p, o2n) = (o2['p'], o2['n']) o = { 'p': "( " + o1p + op + o2p + " )", 'n': "( " + o1n + op + o2n + " )" } .) } . MulDiv<out o> = Pow<out o> { ( "*" (. op = "*" .) | "/" (. op = "/" .) ) Pow<out o2> (. (o1p, o1n) = (o['p'], o['n']) (o2p, o2n) = (o2['p'], o2['n']) o = { 'p': "( " + o1p + op + o2n, 'n': "( " + o1n + op + o2n + " )" } if op == "*": o['p'] += "+" + o1n + "*" + o2p else: o['p'] += "-" + o1n + "*" + o2p + "/(" + o2n + "^2)" o['p'] += " )" .) } . Pow<out o> = Single<out o> [ "^" Number<out o2> (. (o1p, o1n) = (o['p'], o['n']) (o2p, o2n) = (o2['p'], o2['n']) o = { 'p': "( " + o2n + "*" + o1p + "*" + o1n + "^" + (int(o2n) - 1) + " )", 'n': "( " + o1n + "^" + o2n + " )" } .) ] . Single<out o> = Number<out o> | Var<out o> | "(" In<out o> ")" | Function<out o> . это простой вариант (проверьте на правильность. не проверял). только +, -, *, /, степень в число, (), ну и функции которые добавите и напишете обработчики по приведеным правилам. те на выход подается словарь, где p = строка с производной, а n = строка без производной (исходная). число и название переменной в скобки не брать, "+"/"-" - брать. остальное по желанию. скобки эти таки жуть, но они прообраз дерева
Интересно, а что твоя прога будет делать, если сначала задать полином как x^5+x^4... а потом как (x+5)(x+4)(x+3)... Даже если правильно напишешь дерево или стек чтобы отловить производную сложной функции или длинного произведения то результат даже от простых примеров может получиться хотя и правильным но совершенно неудобоваримым тк нужно еще уметь сокращать, выносить или вносить за скобки, приводить общие члены и тд
вот рабочий экзампл годный для копипастинга. я там поубирал большинство скобок, но нужно проверить - не стер ли что лишнее Код (Text): COMPILER P IGNORECASE CHARACTERS letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". digit = "0123456789". op = "+-*/^" . par = "()" . eol = CHR(13) . lf = CHR(10) . TOKENS number = digit {digit} . name = letter {letter | digit} . COMMENTS FROM '#' TO eol IGNORE eol + lf PRODUCTIONS P = [ In<out o> (. print o['p'] .) ] EOF . //---------------------------------------------------------------------------- In<out o> = (. o = '' .) AddSub<out o> . AddSub<out o> = MulDiv<out o> { ( "+" (. op = "+" .) | "-" (. op = "-" .) ) MulDiv<out o2> (. (o1p, o1n) = (o['p'], o['n']) (o2p, o2n) = (o2['p'], o2['n']) o = { 'p': o1p + op + o2p, 'n': o1n + op + o2n } .) } . MulDiv<out o> = Pow<out o> { ( "*" (. op = "*" .) | "/" (. op = "/" .) ) Pow<out o2> (. (o1p, o1n) = (o['p'], o['n']) (o2p, o2n) = (o2['p'], o2['n']) o = { 'p': "( " + o1p + op + o2n, 'n': "( " + o1n + op + o2n + " )" } if op == "*": o['p'] += "+" + o1n + "*" + o2p else: o['p'] += "-" + o1n + "*" + o2p + "/(" + o2n + "^2)" o['p'] += " )" .) } . Pow<out o> = Single<out o> [ "^" Number<out o2> (. (o1p, o1n) = (o['p'], o['n']) (o2p, o2n) = (o2['p'], o2['n']) o = { 'p': o2n + "*(" + o1p + ")*" + o1n + "^" + str(int(o2n) - 1), 'n': o1n + "^" + o2n } .) ] . Single<out o> = Function<out o> | Number<out o> | Var<out o> | "(" In<out o1> ")" (. o = { 'p': "( " + o1['p'] + " )", 'n': "( " + o1['n'] + " )" } .) . Var<out o> = name (. o = { 'p': '1', 'n': self.token.val } .) . Number<out o> = number (. o = { 'p': '0', 'n': self.token.val } .) . Function<out o> = "sin" "(" In<out o1> ")" (. (o1p, o1n) = (o1['p'], o1['n']) o = { 'p': " cos(" + o1n + ")*(" + o1p + ")", 'n': "sin(" + o1n + ")" } .) | "cos" "(" In<out o1> ")" (. (o1p, o1n) = (o1['p'], o1['n']) o = { 'p': " -sin(" + o1n + ")*(" + o1p + ")", 'n': "cos(" + o1n + ")" } .) . END P. на предложенном выше примере выдает строку чтобы поубирать и сократить надо делать хоть примитивное промежуточное дерево и сокращать его. расширить возможности, можно пользуясь приведенным экзамплом и http://ru.wikipedia.org/wiki/Таблица_производных если захочется, все же, оптимизации + сокращения, то это не счас. нг на носу однако! выпьем! YY !
читал топик, не смог понять какой сложности нужно брать производные. нужна ли всякие там бессели, гамма функции и пр. в каком виде задана исходная функция - явном или неявном. я так думаю, для произвольной записи, в общем случае эта задача нерешаема, имхо. хотя, maple, вроде и вычисляет, правда, далеко не всегда оптимально.
maksim_ чяго чяго? Брат максимка, это ты путаешь дифференцыалы с интегралами, чего делать никак не стоит. Проиизводная всегда легко вычислима и прога для этого нужна не сложнее калькулятора со скобками.
это говорит о том, что ты не брал производных от сложных функций. от степенных - понятное дело просто.
cupuyc Без разницы. Как говорил наш препод по ТДУ - "дифференцирование - ремесло, интегрирование - искусство!"