Gleichungen in Variablen speichern !

GartenUmgraben

Erfahrenes Mitglied
Moin, hab da ein Problem.

Hier mal eine einfaches Beispiel zu dem Problem.

Ich habe eine Variable a die sich aus a = b+ c ergibt. Abhängig von einem bestimmten Parameter ändert sich die Gleichung ab und zu zu a = b - c

Das tut die mehrfach im Programm und ich habe keine Lust immer die komplette Formel oder gar ne eigen Funktione dafür zu schreiben.

Meine Frage nun, kann man eine Gleichung alà "b-c" in eine Variable packen ?

sprich:


gl1 = b - c;
gl2 = b + c;


und dann später einfach immer nur a = gl1 bzw a= gl2 nutzen. Wichtig ist dabei, das halt bei jeder zuweisung a = gl... die Berechnung b+c bzw b-c erneut durchgeführt wird!


Gruß

Gärtner
 
Nö das geht nicht, da Variablen etwas zugewiesen wird und dann nicht jedesmal neu berechnet wird.

Aber erstelle Dir doch einfach zwei statische Methoden gl1 und gl2 die die Berechnung durchführen.

Grüße
Speedkill
 
Thema wurde von mir verschoben, da es nichts mit Windows Forms zu tun hat. Bitte nachdenken, wohin die entsprechenden Posts wirklich gehören.
 
Einfacher als mit Funktionen gehts glaub ich nicht.

Etwas dynamischer gehts mit Delegates. All deine Gleichungsfunktionen müssen einfach die selben Parameter verlangen. Hier hast du den Vorteil, dass du die Gleichung zuweisen kannst, bevor du die Argumente kennst.

Oder du schnappst dir eine Scripting Engine (<werbung>z.B. meine: CSC4</werbung>) und das sieht dann etwa so aus:
C#:
import System;
import System.Collections.Generic;
import CSC4;

class problem
{
	private Engine myEngine = new Engine("myEngine");
	private Application myApp = new Application("myApp", myEngine);
	private List<CodeUnit> equations = new List<CodeUnit>();
	
	public void main()
	{
		//Ein ProcedurePrototype ist wie eine Schablone für Funktionen
		Compiler.ProcedurePrototype prototype = new Compiler.ProcedurePrototype();
		prototype.Parameters.Add(new Parameters("a"));
		prototype.Parameters.Add(new Parameters("b"));
		
		prototype.Id = "equation1";
		equations.Add( myApp.CreateCodeUnit("r = a + b"), prototype );
		
		prototype.Id = "equation2";
		equations.Add( myApp.CreateCodeUnit("r = a - b"), prototype );
		
		//Du kannst Funktionen auch dynamische (z.B. in einer Schleife hinzufügen...)
		
		//Ausführen		
		int a = 5; int b = 3;
		
		int choice = Integer.Parse(Console.ReadLine());
		Console.WriteLine(equations(choice).Execute( new object[] {a,b} ));
	}
}
Gegenüber der Delegate Methode hat dieser Ansatz den Vorteil, dass du neue Gleichungen zur Laufzeit hinzufügen und entfernen kannst. Allerdings nimmt das Kompilieren einige Millisekunden in Anspruch und die Bytecode VM kommt nicht an die Performance von .NET heran ;) .

Alternativ könntest du die Gleichungen auch in externen Scriptdateien definieren:
Code:
procedure equation1(a,b):Int32
{ r = a + b }

procedure equation2(a,b):Int32
{ r = a - b }
, welche dann ganz einfach aus deinen Programm heraus aufgerufen werden könnten:
C#:
// .. gleiches setup wie vorher
void main()
{
	myApp.AddFromScript("D:\\Pfad\\Zum\\Script.csc4");
	//Ausführen		
	int a = 5; int b = 3;	
	int choice = Integer.Parse(Console.ReadLine());
	Console.WriteLine(myApp.Execute("equation" + choice, new object[] {a,b} ));
}

Wenn du dich jetzt fragst, ob das nicht etwas zuviel für dein Problem ist, liegst du wahrscheinlich richtig. Ein paar statische Funktionen sollten reichen.

Könntest du sonst dein Problem etwas genauer beschreiben, vielleicht gibt es eine ganz andere Lösung....
 
Mein eigentliches Problem ist in der Tat etwas komplexer.


Also ich habe eine Funktion:

Code:
public float Berechnung()
{
  float ergebnis = 0;

  ergebnis = conf.Gleichung;

  return(ergebnis);
}


des weiteren habe ich unter Visual Studio 05 eine Settingsdatei deren Werte ich per conf.Wert ansprechen kann. Soll heissen "Gleichung" steht als Wert in der Settingsdatei, welche ja im Grunde nur eine XML Datei ist.

In der XML soll nun unter Gleichung folgendes stehen:

conf.Wert1 + conf.wert2

auch "Wert1" und "Wert2" sind entsprechend Werte die in der Settingsdatei stehen.

z.B. Wert1 = 10 Wert2 = 5

so würde das Ergebniss also 15 lauten.

Das ganze wird dann kompiliert.

Wenn nun der User meint, dass das Ergebniss der Funktion anders zu berechnen sei, dann kann er einfach in die XML gehen, und den Wert für "gleichung" entsprechend angleichen. Z.B.

conf.Wert1 - conf.Wert2

so dass als ergebniss 5 rauskäme.


Evtl soll sogar möglich sein (bin nich sicher ob machbar) in die Gleichung einen weiteren parameter (z.B. Wert3) hinzuzufügen der dann ggf erst vom User in die XML eingefügt werden muss.

Ziel ist eine größtmögliche varabilität der Anwendung, wobei alle ohne neukompilierung anpassbar sein soll..wie eben z.B. die Sache mit der Gleichung.


Gruß

Gärtner
 
Hm... dynamische Ausdrücke...

3 Möglichkeiten:
  1. Zur Laufzeit in .NET Code kompilieren
  2. Einen eigenen Parser/Interpreter schreiben
  3. Eine Scripting Engine verwenden

Zu 1: Relativ grosser overhead, da ein komplettes Assembly kompiliert werden muss. Einmal kompilierter Code kann nicht mehr aus dem Speicher entfernt werden. Eignet sich also nicht, wennn die Gleichungen zur Laufzeit ändern könnten. Auf der anderen Seite bietet diese Variante die beste Performance nachdem der Code einmal kompiliert wurde.

Zu 2: Relativ grosser Aufwand, wenn du nicht mit dem Gebiet vertraut bist. Lässt sich aber perfekt an deine Wünsche anpassen. Flexibilität und Ausführgeschwindigkeit hängen von deinen Programmierkünsten ab ;)

Zu 3: Ich kann wieder nur von meiner Engine sprechen: Die Ausdrücke sind schnell übersetzt und können während der Laufzeit problemlos ersetzt/gelöscht werden. Bis auf Delegates, Events und die Definition eigener Datentypen beherrscht CSC4 alles, was .NET zu bieten hat.

Hab dein Szenario mal mit CSC4 programmiert:
C#:
class MyProgram
{
	
	private Engine myEngine;
	private Application myApp;
	private List<CodeUnit> expressions;   

	public MyProgram()
	{
		myEngine = new Engine("myEngine");
		myApp = new Application(myEngine, "myApp");
		//Schreibgeschützte, globale Variable mit den Settings erstellen, damit die Ausdrücke darauf zugreifen könne. 
		myApp.RequestNewVariable("config", new CVar(new CValue(Properties.Settings.Default ), false));
		expressions = new List<CodeUnit>();
	}

	private CodeUnit CompileExpression(string name, string expression)
	{
		return myApp.CreateCodeUnit("r = (" + expression + ")", name, typeof(object));
	}

	public void main()
	{
		Console.WriteLine("Kompiliere Ausdrücke");
		//Ausdrücke kompilieren
		expressions.Add(CompileExpression("ausdruck1", Properties.Settings.Default.Ausdruck1));
		expressions.Add(CompileExpression("ausdruck2", Properties.Settings.Default.Ausdruck2));
		//Du kannst Funktionen auch dynamische (z.B. in einer Schleife hinzufügen...)

		//Ausführen  
		Console.WriteLine("Welchen Ausdruck möchtest du anwenden? 1 oder 2?");
		int choice = Int32.Parse(Console.ReadLine());
		Console.WriteLine("Das Ergebnis ist: {0}",expressions[choice-1].Execute());
		Console.ReadLine();
	}
}
Im Anhang sollte das komplette VS2005 Projekt sein. Gib entweder 1 oder 2 ein. Du kannst die Gleichungen in der *.config Datei ändern ;)

Bitte beachte, dass die mitglieferte Version der CSC4Engine einige Overloads enthält, die es noch nicht in die offizielle SourceForge.net Version geschafft haben. Falls du CSC4 verwenden möchtest, werde ich die neue Version freigeben.
 

Anhänge

  • DynamischeAusdruecke.zip
    9,1 KB · Aufrufe: 16

Neue Beiträge

Zurück