Mathematische Funktionen

Für Fragen von Einsteigern und Programmieranfängern...
masterm
Beiträge: 15
Registriert: Do 11. Okt 2012, 18:56
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Mathematische Funktionen

Beitrag von masterm »

Hey Community,

ich habe da ein Problem, und zwar: Ich möchte ein Programm schreiben, dass mithilfe des Newtonverfahrens (falls jemand wissen möchte, was es ist, hier ein Link: https://www.mathematik.de/ger/fragenant ... ahren.html" onclick="window.open(this.href);return false;) die Nullstelle einer mathematischen Funktion berechnet. Ich habe dafür schonmal einen Quellcode vorgefertigt:

Code: Alles auswählen

 
unit NewtonverfahrenProgramm;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    funktion2: TEdit;
    funktion1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Memo1: TMemo;
    Panel1: TPanel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Memo1Change(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    function f(x:real):real;
    function f_1_Abl(x:real):real;
  end;
 
var x,x0:real;i,anz:integer;
 
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
function TForm1.f(x:extended):extended;
begin
  Result:=x*x*x-9;
end;
 
function TForm1.f_1_Abl(x:real):real;
begin
  Result:=3*x*x;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var a: array [1..1,1..32000] of String;
begin
x0:= strtofloat (funktion1.Text);
anz:= strtoint (funktion2.Text);
 for i:=1 to (anz) do
 begin
 x := (x0)-(f(x0)/f_1_Abl(x0));
 x0:=x;
 a[1,i]:=floattostr (x0)
 end;
 for i:=1 to (anz-1) do
 begin
 Memo1.lines.add(a[1,i]);
 end;
Label1.Caption:= floattostr (x0);
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
  funktion1.Text:= '';
  funktion2.Text:= '';
  x:=0;x0:=0;
  for i:=1 to (anz) do begin
  Memo1.lines[i]:= ''
  end;
  i:=0;anz:=0;
Label1.Caption:= 'Näherungswert'
end;
 
procedure TForm1.Memo1Change(Sender: TObject);
begin
 
end;
 
end.
Das Verfahren an sich funktioniert im Programm sehr gut, er gibt mir auch alle richtigen Werte, soweit so gut. Jetzt aber zum Problem. Im Quellcode habe ich die Funktion und ihre Ableitung schon vorgegeben:

Code: Alles auswählen

function TForm1.f(x:real):real;
begin
  Result:=x*x*x-9;
end;
 
function TForm1.f_1_Abl(x:real):real;
begin
  Result:=3*x*x;
end;
Ich habe dies als Beispiel gemacht, um zu gucken, ob er mir alle richtigen Werte herausgibt. Jetzt möchte ich aber, dass keine bestimmte Funktion vorgegeben ist (also, in meinem Fall war es hier x*x*x-9), sondern dass der User selbst eine bestimmte Funktion (und die Ableitung dazu) eingibt, und das Programm es dann genauso berechnet. Und ein Term wie zum Beispiel x*x-3 oder so ist ja nicht vom Typ Integer oder Real (sodass hier die einfachen Befehle wie strtofloat or strtoint entfallen ^^).
Hat einer eine Idee, wie man es machen könnte ?

Ich sag schonmal Danke für jeden Comment oder Lösungsvorschlag. ;)

masterm

amrs
Beiträge: 9
Registriert: Fr 12. Okt 2012, 22:55
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: 32Bit

Re: Mathematische Funktionen

Beitrag von amrs »

Hallo Masterm,

ich habe soetwas vor ein paar Jahren in der Sprache Icon programmiert.

Eine beliebig verschachtelte Funktion wird als Zeichenkette eingegeben. Ein Funktionsplotter lässt sich so realisieren, dass eine Schleifenvariable mit angegebener Schrittweite das angegebene Intervall durchläuft. Ein Parser untersucht die Zeichenkette, ersetzt 'x' durch die Schleifenvariable und ersetzt alle mathematischen Ausdrücke durch die entsprechenden Operatoren oder Funktionen.

Auf ähnliche Weise lassen sich auch Ableitungen analytisch ermitteln.

Es ist eine nette Programmierübung - und wenn's denn funktioniert, kommt Begeisterung auf.

Gutes Gelingen!

Andreas

masterm
Beiträge: 15
Registriert: Do 11. Okt 2012, 18:56
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Mathematische Funktionen

Beitrag von masterm »

amrs hat geschrieben:Eine beliebig verschachtelte Funktion wird als Zeichenkette eingegeben. Ein Funktionsplotter lässt sich so realisieren, dass eine Schleifenvariable mit angegebener Schrittweite das angegebene Intervall durchläuft. Ein Parser untersucht die Zeichenkette, ersetzt 'x' durch die Schleifenvariable und ersetzt alle mathematischen Ausdrücke durch die entsprechenden Operatoren oder Funktionen.

Auf ähnliche Weise lassen sich auch Ableitungen analytisch ermitteln.

Es ist eine nette Programmierübung - und wenn's denn funktioniert, kommt Begeisterung auf.

Gutes Gelingen!

Andreas
Hey, danke schonmal für diese schnelle Antwort.

also, erstmal wollt ich etwas sagen, was die Ableitungen angeht. Diese wollte ich im Programm erstmal weglassen (eine Herausforderung für mich für später), also, der User wird sie sozusagen selbst eingeben müssen, denn ich wollte nur, dass erstmal überhaupt das Newtonverfahren anwendbar ist.

Dann muss ich hier wirklich gestehen, dass ich mich erst seit ein paar Wochen mit Lazarus und Turbo Pascal beschäftige, und auch deshalb das hier in Einsteigerfragen hineinschreibe, denn z. B. weiß ich jetzt auch nicht, was du mit Parser meinst bzw. was das überhaupt ist. ^^

Eine Schleifenvariable dürfte glaube ich eine Zahl vom Typ Integer oder Byte sein, oder ? Ansonsten, wie das Ersetzen durch Operatoren und Funktionen geht, hab ich jetzt auch keinen Schimmer, wie gesagt, ich bin erst grad in der Einstiegsphase.

MfG masterm

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: Mathematische Funktionen

Beitrag von u-boot »

Naja ... kommt drauf an, wie beliebig das ganze wirklich werden soll.

Bisher stehen als Beispiele ja nur Polynomfunktionen da. Wenn es bei diesen bleiben soll, könnte man ja auch eine Maske anfertigen wo man nur Koeffizienten bis zu einem vorgegebenen Grad eintragen darf/kann/braucht. Dann würde das ganze auch mit der Ableitung usw. einfach gehn.

Die Frage ist, will man mehr oder nicht... falls ja, wirds wohl auf parsen usw. rauslaufen.
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: Mathematische Funktionen

Beitrag von u-boot »

http://de.wikipedia.org/wiki/Parser

naja als Dauereinsteiger wie mir reicht es, dass ein Parser einen Text in etwas programmtechnisch brauchbares umwandelt....
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Mathematische Funktionen

Beitrag von Euklid »

masterm hat geschrieben: Hat einer eine Idee, wie man es machen könnte ?

Ich sag schonmal Danke für jeden Comment oder Lösungsvorschlag. ;)
Es gibt bereits ein paar FreePascal-Parser. Der bei diesem Programm verwendete Parser unterstützt auch Ableitungen beliebiger Ordnung: http://www.promathika.de" onclick="window.open(this.href);return false;

Wenn Du da Interesse hast, kannst Du das hier mal kund tun, dann würde ich das Einbinden des dort verwendeten Parsers näher erläutern.

Viele Grüße, Euklid

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1617
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Mathematische Funktionen

Beitrag von corpsman »

Was du brauchst ist etwas wie meine GenMathCalc Komponente. Mit dieser und dem Tokenizer kann man sich einen Mathematischen solver inwenigen schritten selbst bauen. Du musst dann lediglich die Callbacks schreiben.

Gruß

Corpsman
--
Just try it

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Mathematische Funktionen

Beitrag von mschnell »

Mein Sohn hat vor einigen Jahren mal ein Programm zur nichtlinearen Ausgleichsrechnung (Kurven-Anpassung) geschrieben. Da haben wir sehr erfolgreich den "HAM-Parser" verwendet: http://www.delphipraxis.net/59668-der-ham-parser-2.html.

Vorteil für iterative Verfahren: die Textform der Formel wird nicht bei jedem Aufruf neu interpretiert, sondern vorübersetzt und ist somit bei häufigem Aufruf viel schneller.

Gruß,
-Michael

masterm
Beiträge: 15
Registriert: Do 11. Okt 2012, 18:56
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Mathematische Funktionen

Beitrag von masterm »

corpsman hat geschrieben:Was du brauchst ist etwas wie meine GenMathCalc Komponente. Mit dieser und dem Tokenizer kann man sich einen Mathematischen solver inwenigen schritten selbst bauen. Du musst dann lediglich die Callbacks schreiben.
Wie schon gesagt, ich beschäftige mich mit Lazarus und FreePascal erst seit kurzer Zeit und kratz noch sozusagen an der Oberfläche von dem, was möglich ist. ^^
Also, wenns da wirklich so einfach gehen sollte, wäre es cool, wenn du mir genauer die Schritte erläutern könntest, wie ich diese Komponente selbst baue und einbinde. Und auch weiß ich jetzt nicht, was mit Callbacks gemeint ist (kannst es mir auch per PN erläutern, wenn du willst) ;)
Euklid hat geschrieben:Es gibt bereits ein paar FreePascal-Parser. Der bei diesem Programm verwendete Parser unterstützt auch Ableitungen beliebiger Ordnung: http://www.promathika.de" onclick="window.open(this.href);return false;

Wenn Du da Interesse hast, kannst Du das hier mal kund tun, dann würde ich das Einbinden des dort verwendeten Parsers näher erläutern.
Okey, schon doch ziemlich komplex. Wenn du mir jetzt noch erläutern könntest, wie ich den Parser dort in mein Programm einbinde, wärs super. Ich möcht auch jetzt nicht die Ableitung zu bilden oder sowas geschweige denn Graphen zeichnen, wäre schon viel zu weit für mich. ^^ Mir reicht es, wenn das Programm dann den Term, den er bekommt auch lesen kann und der User selbst die Ableitung erstmal auch selbst eingeben muss. Also, wenn der User z. B. die Funktion f(x):=x*x-4 haben will, dass der dann selbst nur den Term x*x-4 eingeben muss und das Programm von selbst diesen Term weiterverwendet. So als Beispiel.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Mathematische Funktionen

Beitrag von Euklid »

masterm hat geschrieben:Okey, schon doch ziemlich komplex. Wenn du mir jetzt noch erläutern könntest, wie ich den Parser dort in mein Programm einbinde, wärs super.
Kein Problem:
Wenn Du Dir den Quelltext runterlädst und das Verzeichnis entpackst, siehst Du im Verzeichnis ganz viele Dateien mit der Bezeichnung u_prm_kernel_[...].
Das sind alle Dateien, die Du benötigst. Kopiere sie einfach in das Quelltextverzeichnis Deines Projekts. Dann:

1. Öffne in Deinem Projekt die Datei u_prm_kernel.pas und binde die Unit u_prm_kernel in dem uses-Bereich Deines Projektes ein.
2. Definiere im var-Bereich eine Variable vom Typ tAnalyse.

Code: Alles auswählen

var CAS: tAnalyse;
3. Jetzt muss das Objekt erstellt werden:

Code: Alles auswählen

CAS := tAnalyse.Create;
4. Den Funktionsterm gibst Du jetzt wie folgt ein:

Code: Alles auswählen

CAS.FEing('x*x-4');
5. Den Funktionswert z.B. an der Stelle 5 errechnest Du dann durch:

Code: Alles auswählen

var
[...]
    y:extended;
[...]
y := FWert(5);
6. Die Ableitung nach der Variablen x bildest Du durch:

Code: Alles auswählen

 
var
[...]
    Ableitungsterm: string;
[...]
Ableitungsterm := SAbleitung('x*x-4','x');
7. Zum Schluss musst Du das Objekt wieder freigeben:

Code: Alles auswählen

CAS.Free;
Viele Grüße, Euklid

masterm
Beiträge: 15
Registriert: Do 11. Okt 2012, 18:56
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Mathematische Funktionen

Beitrag von masterm »

Euklid hat geschrieben:1. Öffne in Deinem Projekt die Datei u_prm_kernel.pas und binde die Unit u_prm_kernel in dem uses-Bereich Deines Projektes ein.
2. Definiere im var-Bereich eine Variable vom Typ tAnalyse.

Code: Alles auswählen

var CAS: tAnalyse;
3. Jetzt muss das Objekt erstellt werden:

Code: Alles auswählen

CAS := tAnalyse.Create
4. Den Funktionsterm gibst Du jetzt wie folgt ein:

Code: Alles auswählen

CAS.FEing('x*x-4');
5. Den Funktionswert z.B. an der Stelle 5 errechnest Du dann durch:

Code: Alles auswählen

var
[...]
    y:extended;
[...]
y := FWert(5);
6. Die Ableitung nach der Variablen x bildest Du durch:

Code: Alles auswählen

 
var
[...]
    Ableitungsterm: string;
[...]
Ableitungsterm := SAbleitung('x*x-4','x');
7. Zum Schluss musst Du das Objekt wieder freigeben:

Code: Alles auswählen

CAS.Free;
Viele Grüße, Euklid
So, also das Einbinden der Datei im Projekt und dann im Uses-Bereich hat auch super funktioniert. Doch nun weiter: Du hast hier ja einen bestimmten Term vorgegeben. Ich möcht aber so ein Programm machen, dass wenn der User in ein Editfeld einen Term eingibt, dass dieser ihn sozusagen auswertet und in die Funktion einfügt, die ich ja in meinem function-Befehl hatte:
masterm hat geschrieben:
function TForm1.f(x:extended):extended;
begin
Result:=x*x*x-9;
end;
Hier hab ich ja meinen Term x*x*x-9 im Quelltext gegeben. Der Term soll aber nicht gegeben sein, sondern der User soll ihn selbst über ein Editfeld bestimmen können (hab ich dir schon in der PN geschrieben, aber ich schreibs hier nochmal ins Forum für alle, falls jemand das gleiche Problem wie ich hat ^^).

masterm

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Mathematische Funktionen

Beitrag von Euklid »

masterm hat geschrieben:Hier hab ich ja meinen Term x*x*x-9 im Quelltext gegeben. Der Term soll aber nicht gegeben sein, sondern der User soll ihn selbst über ein Editfeld bestimmen können
Das lässt sich jetzt relativ schnell realisieren, z.B. durch

Code: Alles auswählen

CAS.FEing(Edit1.Text);
Zumindest glaube ich, dass es das ist, was Du meinst?

Gruß, Euklid

masterm
Beiträge: 15
Registriert: Do 11. Okt 2012, 18:56
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Mathematische Funktionen

Beitrag von masterm »

Ach, geht das wirklich so einfach ? xD Wow, ich probiers mal aus, danke. ^^

Gruß, masterm

PS: Ja, genau das habe ich gemeint, einfach keinen Term vorgegeben haben, sondern sich einen vorgeben lassen. ;)
Zuletzt geändert von masterm am So 14. Okt 2012, 11:39, insgesamt 1-mal geändert.

masterm
Beiträge: 15
Registriert: Do 11. Okt 2012, 18:56
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: Mathematische Funktionen

Beitrag von masterm »

So einfach wie ich es hier gemacht habe, geht es natürlich nicht ^^ :

Code: Alles auswählen

function f(x:real):real;
[....]
var CAS:tAnalyse;
[....]
function TForm1.f(x:real):real;
begin
CAS := tAnalyse.Create;
CAS.FEing(Edit1.Text);
Result:=CAS;
CAS.Free;
end;
Als Fehler gibt er mir "Incompatible types: got tAnalyse expected Real". Ich seh auch, dass es mit den Typen so nicht klappen kann, aber wie kann ich es da in diese Funktion einfügen ?

Grüße

masterm
Zuletzt geändert von Lori am Mo 15. Okt 2012, 17:15, insgesamt 1-mal geändert.
Grund: Highlighter

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Mathematische Funktionen

Beitrag von Euklid »

Code: Alles auswählen

Result:=CAS.FWert(x);
;)

Antworten