mathematische Formeln, umformungen nicht einzeln implementieren

barelli

Mitglied
Hallo Zusammen,

zur zeit programmiere ich ein Programm, welches diverse Dinge berechnen kann.
Dies tut es anhand mathematischer Formeln.
Die Eingaben die getätigt werden, können ja variiert werden, das heißt, wenn ich zum Beispiel eine Formel habe für das Volumen eines Zylinders:
Pi * r^2 * h = V
kann ich ja entweder r und h eingeben und V bekommen, oder ich könnte genau so gut fragen: Gegeben sind höhe und Volumen, wie muss der Radius sein?

Nun möchte ich nicht jede einzelne Umformung implementieren, exisitert eine Möglichkeit so etwas geschickt zu lösen?

Ich hoffe man kann verstehen was ich meine.

MfG barelli
 

Marco13

Top Contributor
Vielleicht ein Hinweis auf den möglichen Grund, warum noch niemand geantwortet hat: Wenn man das nicht für eine bestimmte Formel "hertverdrahtet" hinschreiben will, geht sowas schnell in Richtung eines Computeralgebrasystems... und sowas schreibt man eben nicht mal so locker-flockig aus dem Handgelenk hin...
 

Landei

Top Contributor
Solange alles bei multiplikativen Formeln mit ganzzahligen Exponenten bleibt, mag es noch gehen. Dazu sollte man allerdings alles erst mal auf eine Seite bringen: Pi * r^2 * h * V^-1 = 1

Hier ein wenig Code:
Java:
public class Variable {
   private final String name;
   private final String description;
   private final int exponent;

   private double value = Double.NaN;

   public Variable(String name, int exponent, String description) {
       this.name = name;
       this.exponent = exponent;
       this.description = description;
       if (exponent == 0) {
           throw new IllegalArgumentException("Exponent must be non-zero.");
       }
   }

   public Variable(String name, int exponent) {
       this.name = name;
       this.exponent = exponent;
       this.description = name;
   }

   public double get() {
       return value;
   }

   public void set(double value) {
       this.value = value;
   }

   public boolean isSet() {
       return ! Double.isNaN(value);
   }

   public void clear() {
       this.value = Double.NaN;
   }

   @Override public String toString() {
       return name + (isSet() ? " = " + value : "");
   }

   public String getName() {
       return name;
   }

   public String getDescription() {
       return description;
   }

   public int getExponent() {
       return exponent;
   }
}

Java:
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author Gronau
 */
public class Formula {

    private final double constant;
    private final String name;
    private final Map<String, Variable> variables = new TreeMap<String, Variable>();

    public Formula(String name, double constant, Variable... variables) {
        this.constant = constant;
        this.name = name;
        for (Variable v : variables) {
            this.variables.put(v.getName(), v);
        }
    }

    public Formula(String name, Variable... variables) {
        this(name, 1, variables);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(name).append(": ");
        sb.append(constant);
        for (Variable v : variables.values()) {
            sb.append('*').append(v.getName()).append('^').append(v.getExponent());
        }
        sb.append(" = 1");
        return sb.toString();
    }

    public void clear() {
        for (Variable v : variables.values()) {
            v.clear();
        }
    }

    public boolean set(String variableName, double value) {
        Variable v = variables.get(variableName);
        if (v != null) {
            v.set(value);
            return true;
        } else {
            return false;
        }
    }

    public double get(String variableName) {
        Variable v = variables.get(variableName);
        return (v != null) ? v.get() : Double.NaN;
    }

    public boolean canCalculate() {
        int unset = 0;
        for (Variable v : variables.values()) {
            if (!v.isSet()) {
                unset++;
            }
        }
        return unset == 1;
    }

    public Variable calculate() {
        Variable result = null;
        double value = constant;
        for (Variable v : variables.values()) {
            if (!v.isSet()) {
                if(result != null) {
                    throw new ArithmeticException("Formula has more than one unset variable.");
                }
                result = v;
            } else {
                value *= Math.pow(v.get(), v.getExponent());
            }
        }
        if(result == null) {
          throw new ArithmeticException("Formula has no unset variable.");
        }
        result.set(Math.pow(value, -1.0/result.getExponent()));
        return result;
    }

}

Und so ruft man es auf:
Java:
    public static void main(String[] args) {
        Formula f = new Formula("cylinder", Math.PI,
                new Variable("r",2,"radius"),
                new Variable("h",1,"height"),
                new Variable("V",-1,"volume"));
        System.out.println(f); //--> cylinder: 3.141592653589793*V^-1*h^1*r^2 = 1
        f.set("h", 2);
        f.set("r", 3);
        System.out.println(f.calculate()); //--> V = 56.548667764616276
        f.clear();
        f.set("h", 2);
        f.set("V", 56.548667764616276);
        System.out.println(f.calculate()); //--> r = 3.0
 
Zuletzt bearbeitet:

Yamato

Aktives Mitglied
Wenn man auf die Implementierung eines CAS verzichten will, geht es wohl nur mit Numerik - zumindest, wenn man beliebig komplexe Formeln zulassen will.

Hat man z. B. eine Gleichung g(x1, x2, ..., xn) = 0 und soll beispielsweise nach x5 umgestellt werden, so muss man die Gleichung

f(x5) = g(x1, ..., x5, ..., xn) = 0 (da alle Variablen außer x5 fest sind)

lösen, was man z. B. mit dem Sekantenverfahren numerisch lösen kann.
 

Landei

Top Contributor
In der Praxis lassen sich aber die meisten Formeln auf wenige Grundtypen zurückführen: Multiplikation von Potenzen (wie oben), Konstante mal e hoch irgendwas u.s.w.
 

barelli

Mitglied
hallo,

herzlichen dank für eure beitrage!

ich werde die genannten denkanstöße vertiefen und mich melden sobald ich es etwas brauchbares habe.

viele grüße barelli
 

Marco13

Top Contributor
Solange alles bei multiplikativen Formeln mit ganzzahligen Exponenten bleibt, mag es noch gehen.
...
In der Praxis lassen sich aber die meisten Formeln auf wenige Grundtypen zurückführen: Multiplikation von Potenzen (wie oben), Konstante mal e hoch irgendwas u.s.w.

Ja gut, man könnte sagen: Je allgemeingültiger das ganze sein soll, und je weniger Annahmen man über die Struktur der Formel machen will, umso aufwändiger (CAS-ähnlicher) wird's.... ;)
 

Ähnliche Java Themen

Neue Themen


Oben