Wie programmiert man die Ableitungen einer Funktion ?

Neue Frage »

Auf diesen Beitrag antworten »
Bilbo Beutlin aus Auenland Wie programmiert man die Ableitungen einer Funktion ?

Meine Frage:
Info Unterricht.

Meine Ideen:
ich hab keine
 
Auf diesen Beitrag antworten »
Brustwarzenzwicker2000 RE: Wie programmiert man die Ableitungen einer Funktion ?

fu yo echt hart brudi du solltes mal probieren deinen Cock auf den PC zu platzieren und so die Software neu zu konfigurieren
Auf diesen Beitrag antworten »
eulerscheZahl

Das kommt darauf an, wie kompliziert die Funktion sein kann. Bei Klammerausdrücken, trigonometrischen Funktionen, ... rate ich zu einem Binärbaum zur internen Abspeicherung. Das aufwändige ist der Parser (wie die Funktion zerlegt wird), das Ableiten ist dann nicht mehr schwer.
Ich habe so etwas vor einiger Zeit mal programmiert, hier die wesentlichen Zeilen, ein fertiges Programm ist im Anhang.
(nicht ganz sauber programmiert, das Programm war nur für mich gedacht)

Im Ordner ...\Plotter\Plotter\bin\Debug ist ein lauffähiges Programm

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
    public class Differenzierer : Parser
    {
        public static string Ableiten(string nach, Parser abzuleiten)
        {
            string erg = AbleitenRek(nach, abzuleiten.wurzel);
            string tmp = "";
            while (tmp != erg)
            {
                tmp = erg;
                Parser p = new Parser(erg);
                p.Simplify();
                erg = p.ToString();
            }
            return erg;
        }

        private static string AbleitenRek(string nach, Knoten k)
        {
            if (k.rechts == null && k.links == null) //nur noch Konstante
            {
                if (k.op == nach) return "1";
                return "0";
            }
            if (k.links == null) //z.B. sin(x)
            {
                switch (k.op)
                {
                    case "-": return "(-(" + AbleitenRek(nach, k.rechts) + "))";
                    case "sin": return "(cos(" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))";
                    case "cos": return "(-sin(" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))";
                    case "tan": return "(1/cos(" + k.rechts.ToString() + ")^2*(" + AbleitenRek(nach, k.rechts) + "))";
                    case "ln": return "(1/(" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))";
                    case "lg": return "(1/(ln(10)*(" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + ")))";
                    case "log": return "(1/(ln(" + k.rechts.links + ")*(" + k.rechts.rechts.ToString() + ")*(" + AbleitenRek(nach, k.rechts.rechts) + ")))";
                    case "abs": return "((" + k.rechts.ToString() + ")/abs(" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))";
                }
            }
            switch (k.op)
            {
                case "+": return "((" + AbleitenRek(nach, k.links) + ")+(" + AbleitenRek(nach, k.rechts) + "))";
                case "-": return "((" + AbleitenRek(nach, k.links) + ")-(" + AbleitenRek(nach, k.rechts) + "))";
                case "*": return "(" + AbleitenRek(nach, k.links) + ")*(" + k.rechts.ToString() + ")+(" + k.links.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + ")";
                case "/": return "((" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.links) + ")-(" + k.links.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))/((" + k.rechts.ToString() + ")^2)";
                case "^":
                    if (k.links.op == "e") return "((" + k.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))"; //e-Funktion ableiten
                    return "(((" + k.links.ToString() + ")^((" + k.rechts.ToString() + ")-1))*(((" + k.rechts.ToString() + ")*(" + AbleitenRek(nach, k.links) + "))+((" + k.links.ToString() + ")*ln(" + k.links.ToString() + ")*(" + AbleitenRek(nach, k.rechts) + "))))";
            }
            return "0";
        }
    }


    public class Parser
    {
        public class Knoten
        {
            Knoten _rechts, _links;
            string _op;
            public Knoten rechts { get { return _rechts; } set { _rechts = value; } }
            public Knoten links { get { return _links; } set { _links = value; } }
            public string op { get { return _op; } set { _op = value; } }

            public Knoten()
            {
                this._op = "";
            }

            public override string ToString()
            {
                if (this.rechts == null && this.links == null) //nur noch Konstante
                    return this.op;
                if (this.links == null) //z.B. sin(x)
                {
                    if (this.op == "-" && GetPrioritaet(this.rechts.op) > GetPrioritaet(this.op)) return this.op + this.rechts.ToString();
                    return this.op + "(" + this.rechts.ToString() + ")";
                }
                //operator mit rechtem und linkem Wert
                string l = this.links.ToString();
                string r = this.rechts.ToString();
                if (GetPrioritaet(this.op) > GetPrioritaet(this.links.op)) l = "(" + l + ")";
                if (GetPrioritaet(this.op) > GetPrioritaet(this.rechts.op) || (this.op == "-" && this.rechts.op == "+" || this.op == "/" && this.rechts.op == "*")) r = "(" + r + ")";
                return (l + this.op + r);
            }

            internal bool IsNumber()
            {
                try
                {
                    double.Parse(this.op);
                    return true;
                }
                catch (Exception)
                {
                }
                return false;
            }

            internal void Null()
            {
                this.rechts = null;
                this.links = null;
            }

            public void Zuweisung(Knoten k)
            {
                this.op = k.op;
                this.rechts = k.rechts;
                this.links = k.links;
            }
        }

        private class Operator
        {
            string _op;
            int _prioritaet;
            public string op { get { return _op; } }
            public int prioritaet { get { return _prioritaet; } }
            public Operator(string op, int prioritaet)
            {
                this._prioritaet = prioritaet;
                this._op = op;
            }
        }

        static Operator[] operatoren = {
                                    new Operator(";", 0), //für Basis bei Logarithmus (/Wurzel)
                                    new Operator("+", 1), new Operator("-", 1),
                                    new Operator("*", 2), new Operator("/", 2),
                                    new Operator("^", 3),
                                    new Operator("sin", 4), new Operator("cos", 4), new Operator("tan", 4), new Operator("lg", 4), new Operator("ln", 4), new Operator("log", 4), new Operator("abs", 4)
                                };

        private static int GetPrioritaet(string operat)
        {
            foreach (Operator o in operatoren)
                if (operat == o.op) return o.prioritaet;
            return 10;
        }

        public Knoten wurzel;
        public Parser(string term = "0")
        {
            term = EinfacheEingabe(term);
            wurzel = new Knoten();
            wurzel = ParseRek(term, wurzel);
        }

        public void Simplify()
        {
            SimplifyRek(wurzel);
        }

        private void SimplifyRek(Knoten k)
        {
            if (k.links == null && k.rechts == null) return;
            if (k.links != null) SimplifyRek(k.links);
            if (k.rechts != null) SimplifyRek(k.rechts);
            if (k.links == null)
            {
                //ist eine Funktion
                switch (k.op)
                {
                    case "abs":
                        if (k.rechts.IsNumber())
                        {
                            k.op = Math.Abs(double.Parse(k.rechts.op)).ToString();
                            k.Null(); return;
                        }
                        return;
                    case "-":
                        if (k.op == "-" && k.rechts != null && k.rechts.op == "-" && k.rechts.links == null) //  -(-(x)) = x
                        {
                            k.Zuweisung(k.rechts.rechts); return;
                        }
                        return;
                }
                return;
            }
            if (k.links != null && k.links != null)
            {
                bool numL = k.links.IsNumber(); bool numR = k.rechts.IsNumber();
                switch (k.op)
                {
                    case "+":
                    case "-":
                        if (numL && k.links.op == "0")
                        {
                            if (k.op == "+") k.Zuweisung(k.rechts);
                            else k.links = null;
                            return;
                        }
                        if (numR && k.rechts.op == "0")
                        {
                            k.Zuweisung(k.links); return;
                        }
                        if (numR && numL)
                        {
                            if (k.op == "+") k.op = (double.Parse(k.links.op) + double.Parse(k.rechts.op)).ToString();
                            if (k.op == "-") k.op = (double.Parse(k.links.op) - double.Parse(k.rechts.op)).ToString();
                            k.Null(); return;
                        }
                        if (k.op == "+" && k.rechts.op == "-" && k.rechts.links == null) //  x+(-y) = x-y
                        {
                            k.rechts.Zuweisung(k.rechts.rechts); k.op = "-";
                            return;
                        }
                        if (k.op == "-" && k.rechts.op == "-" && k.rechts.links == null) //  x-(-y) = x+y
                        {
                            k.rechts.Zuweisung(k.rechts.rechts); k.op = "+";
                            return;
                        }
                        return;
                    case "*":
                        if (numL && k.links.op == "1")
                        {
                            k.Zuweisung(k.rechts); return;
                        }
                        if (numR && k.rechts.op == "1")
                        {
                            k.Zuweisung(k.links); return;
                        }
                        if (numL && k.links.op == "0" || numR && k.rechts.op == "0")
                        {
                            k.op = "0"; k.Null(); return;
                        }
                        if (numR && numL)
                        {
                            k.op = (double.Parse(k.links.op) * double.Parse(k.rechts.op)).ToString();
                            k.Null(); return;
                        }
                        if (!numL && numR) //x*2 zu 2*x drehen
                        {
                            Knoten tmp = new Knoten();
                            tmp.Zuweisung(k);
                            k.rechts = tmp.links; k.links = tmp.rechts; return;
                        }
                        return;
                    case "/":
                        if (numR && numL)
                        {
                            k.op = (double.Parse(k.links.op) / double.Parse(k.rechts.op)).ToString();
                            k.Null(); return;
                        }
                        return;
                    case "^":
                        if (numR && k.rechts.op == "0") //x^0 = 1
                        {
                            k.op = "1"; k.Null(); return;
                        }
                        if (numR && k.rechts.op == "1")
                        {
                            k.Zuweisung(k.links); return;
                        }
                        if (numR && numL)
                        {
                            k.op = (Math.Pow(double.Parse(k.links.op), double.Parse(k.rechts.op))).ToString();
                            k.Null(); return;
                        }
                        return;
                }
                return;
            }
        }

        public override string ToString()
        {
            return wurzel.ToString();
        }

        private string EinfacheEingabe(string term)
        {
            term = term.Replace(" ", string.Empty);
            term = term.Replace("²", "^2");
            term = term.Replace("³", "^3");
            term = term.Replace(")(", ")*(");
            while (true) //3x zu 3*x; 3sin(x) zu 3*sin(x)
            {
                Match m = Regex.Match(term, "[0-9][a-zA-Z]");
                if (m.Success)
                    term = term.Insert(m.Index + 1, "*");
                else break;
            }
            int betrag = 0;
            for (int i = 0; i < term.Length; i++)
                if (term[i] == '|')
                {
                    if (++betrag % 2 == 1) term = term.Remove(i, 1).Insert(i, "abs(");
                    else term = term.Remove(i, 1).Insert(i, ")");
                }
            return term;
        }

        private Knoten ParseRek(string term, Knoten k)
        {
            string[] s = Parse(term);
            if (s[1] == "") //keine Funktion mehr, nur Argument
            {
                k.op = s[0];
                k.Null();
            }
            else if (s[0] == "") //z.B. sin(x)
            {
                k.op = s[1];
                k.rechts = new Knoten();
                k.rechts = ParseRek(s[2], k.rechts);
                if (k.op == "+") k.Zuweisung(k.rechts); //unäres Plus im Arsch
                k.links = null;
            }
            else //normaler Operator, mit Wert rechts und links
            {
                k.op = s[1];
                k.rechts = new Knoten();
                k.links = new Knoten();
                k.links = ParseRek(s[0], k.links);
                k.rechts = ParseRek(s[2], k.rechts);
            }
            return k;
        }

        private string[] Parse(string term)
        {
            //finde Operatoren mit niederwertigster Priorität - außerhalb von Klammern
            //Durchlaufen von links nach rechts
            string[] erg = new string[3];
            int klammern = 0, momPrio = 10, stelle = term.Length; string momOp = "";
            for (int i = term.Length - 1; i >= 0; i--)
            {
                if (term[i] == ')') klammern++;
                if (term[i] == '(') klammern--;
                if (klammern != 0) continue;
                foreach (Operator op in operatoren)
                {
                    if (op.prioritaet < momPrio && i + op.op.Length < term.Length && term.Substring(i, op.op.Length) == op.op)
                    {
                        momPrio = op.prioritaet;
                        stelle = i;
                        momOp = op.op;
                    }
                }
            }
            if (momPrio == 10 && term.StartsWith("("))
                return Parse(term.Substring(1, term.Length - 2));
            erg[0] = term.Substring(0, stelle);
            erg[1] = momOp;
            erg[2] = term.Substring(stelle + momOp.Length);
            return erg;
        }
    }
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »