Methoden Funktionenplotter

dbvh2000

Mitglied
Hallo,

im Informatik-Unterricht an einem Gymnasium arbeiten wir momentan an einem Taschen-Rechner. Ich habe mit meinem Team-Partner schon diverse Funktionen programmiert. Wir benutzen als Entwicklungsumgebung für Java BlueJ und nur die Java Basisklasse.

Nun sollen wir hinzufügen, dass man wie bei einem Graphikrechner eine Funktion mit x-Werten eingibt und dann in einem Koordinatensystem der Graph ausgegeben wird.
Unser Lehrer meinte, man könne es auch irgendwie mit einem Array machen.
Wir können dies in zwei Varianten machen:
1. Die einfachere Variante (so wie wir es bis jetzt noch haben): Man hat eine begrenzte Zahl von Kästchen und gibt den x-Wert ein.
2. Schwierigere Variante: Es wird vorher abgefragt, wie hoch der Grad sein soll. Daraufhin gibt man nach und nach für die Polynome den Wert ein und dann wird der Graph ausgegeben.
Was auch nicht so toll ist, ist dass das Fenster wo der Graph ausgegeben wird, sich direkt mit öffnet. Wir haben dass aber mit den ganzen Knöpfen, damit alle funktionieren, nicht besser hinbekommen. Besser wäre, wenn man den provisorischen Hilfe Knopf benutzt: Man benennt ihn um in "Graph" und wenn man drauf klickt öffnet sich das zweite Fenster und es funktioniert alles... Sind halt leider noch Anfänger und können das ganze Programmieren noch nicht so gut ... ;)

Leider kommen wir bei diesem Projekt nicht weiter. Wir wissen nicht, wie man die Probleme löst. Das Projekt muss bald schon abgegeben werden und wird auch benotet...

Ich hoffe, uns kann jemand helfen...
Vielen vielen Dank schon mal für eure Hilfe. :))

Liebe Grüße
Daniel
 

Anhänge

  • Informatik-Projekt TaschenRechner.txt
    17 KB · Aufrufe: 26

Tobse

Top Contributor
Was sind denn eure konkreten Probleme? Woran haperts?

Wisst ihr, wie ihr aus den Eingabedaten des Nutzers die Mathematische Funktion ableitet?
Wisst ihr, wie man diese Funktion plottet?
Oder hängt ihr nur daran, Buttons und Eingabefelder miteinander zu verknüpfen?
 

Tobse

Top Contributor
Gut, dann fangen wir da an. Habt ihr eine Idee, wie ihr bekannte Funktionen wie f(x) = x² oder f(x) = 3x+1 plotten könnt?

Tipp für den Anfang: betrachtet die horizontalen Pixel-Koordinaten (also die X-Koordinaten der Pixel) als Koordinaten eurer X-Achse. Wie ergibt sich dann die Y-Koordinaten für einen Pixel in Abhängigkeit von der zu zeichnenden Funktion?

P.S.: Ich sage deshalb Plotten und nicht zeichnen, weil der Computer nur Pixel hat. Die einzigen Linien, die ein Computer "zeichnen" kann, sind gerade und exakt horizontal oder vertikal. Kurven und schräge Geraden kann der Computer nicht; da muss man tricksen.
 

dbvh2000

Mitglied
@Tobse
Leider nein. Wir haben Informatik noch nicht so lange und können vieles nicht so gut...
Danke schon mal für deine Hilfe... das bringt mir leider trotzdem nichts :(
 

Tobse

Top Contributor
Ihr solltet euch vielleicht zuerst mal ansehen, wie man auf eine Fläche des Bildschirms per Code frei Schnauze Pixel zeichnen kann.

Arbeitet ihr mit Swing? Ich kenne BlueJ nicht. Falls ihr mit Swing arbeitet gibts genug zu dem Thema online. Stichwörter Swing Component, Swing Graphics2D
 

AndiE

Top Contributor
Leider kann ich das Package "basis" für BlueJ nicht öffnen. Es muss ein spezielles Paket eurer Schule sein. Grundlage für das Plotten ist eine Wertetabelle und ein Intervall von x, also eine Angabe, innerhalb welches Bereiches die Funktion geplottert werden soll. Eventuell noch eine Schrittweite. Ich würde da einfach erstmal mit linearen Gleichungen "y=mx+n" anfangen, wobei m und n eingeben werden können.
Würdet ihr das in einem separaten Projekt hinbekommen?

Edit: Habe die Bibliothek gefunden.
 
Zuletzt bearbeitet:

dbvh2000

Mitglied
@AndiE Das mit der Wertetabelle meinte unser Informatik-Lehrer auch, aber wir wissen leider nicht, wie man das umsetzt.
 

Anhänge

  • basisUTF8151112.jar
    270,1 KB · Aufrufe: 18

dbvh2000

Mitglied
@Tobse Ja das wissen wir...

Ich glaube wir haben das irgendwie auch selber noch nicht so richtig verstanden...

In dem Bild sieht man ja die Kästchen, wo man die Zahlen für das x eingibt.
Drückt man dann auf "Graph zeichnen lassen" soll das Programm halt anhand einer Wertetabelle auf der Leinwand in einem Koordinatensystem den Graphen zeichnen.
Ich hoffe ich habe das so richtig aus dem Unterricht verstanden... :D
Könnte man das denn irgendwie umsetzen?

@Tobse Um deine anderen beiden Fragen zu beantworten: Nein, dass wissen wir beides nicht. :(

PS: Wir haben wirk+lich gar keine Ideen ... falls ihr für den Quelltext auch keine Vorschläge habt fragen wir in der nächsten Info-Stunde einfach den Lehrer und schauen dann mal ... :(
_________________________________________________________________
Update > Diesen Ansatz mit dem Array haben wir vom Lehrer letzte Stunde bekommen:

double[] feld;
feld=new double[5];
.
.
.
for(int i=0; i<5; i++) {
feld= ...;
}

Dass man dann halt die Felder feld [0], feld [1], feld [2], feld [3], feld [4] hat.


Info-Projekt.jpg
 

Tobse

Top Contributor
Kein Thema, wir schaffen das :)

Schritt 1: Die funktion, die der User da eingibt, muss ja irgendwie berechnet werden. Wir kennen also die eingegebenen Koeffizienten als ein float[]. Versucht, in dieser Methode die Berechnung unterzubringen:

Java:
public double berechneFVonX(float[] koeffizienten, double x) {
}

Und folgende Werte sollten dabei rauskommen:

Java:
float[] koeffizienten = /* koeffizenten aus UI auslesen */;

// wenn ich eingebe 0 0 0 0 2 3 ist das die Funktion f(x) = 0 * x^5 + 0 * x^4 + 0 * x^3 + 0 * x^2 + 2 * x^1 + 3 * x^0 = 2x + 3
// also ist f(0) = 2 * 0 + 3 = 3, f(1) = 2 * 1 + 3 = 5, f(2) = 2 * 2 + 3 = 7
berechneFVonX(koeffizienten, 0) == 3
berechneFVonX(koeffizienten, 1) == 5
berechneFVonX(koeffizienten, 2) == 7

Testet das mit noch mehr Koeffizienten und werten; stellt 100% sicher, dass diese Methode so arbeitet, wie sie soll.

Schritt 2: Mithilfe dieser Funktion die Wertetabelle befüllen.

Ich nehme jetzt einfach mal an, dass wir den X-Bereich von -10 bis +10 in 0.5er Schritten in der Wertetabelle haben wollen. Wir müssen also f(x) für alle x von -10 bis 10 in 0.5er Schritten berechnen:

Code:
+------+-------+
| x    | f(x)  |
+------+-------+
| -10  |       |
+------+-------+
| -9.5 |       |
+------+-------+
| -9   |       |
+------+-------+
| -8.5 |       |

      ...

|  8.5 |       |
+------+-------+
|  9   |       |
+------+-------+
|  9.5 |       |
+------+-------+
| 10   |       |
+------+-------+

Die Wertetabelle würde ich für den Anfang als eine Map<Double,Double> darstellen. Der Key ist der Wert von x, der zugehörige Wert von f(x).

Versucht mal, in dieser Methode die Wertetabelle zu berechnen:

Java:
public Map<Double,Double> berechneWerteTabelle(float[] koeffizienten) {
}

Wenn ihr das geschafft habt, macht den Startwert von x (-10), den Endwert von x (10) und die Schrittgröße anpassbar:

Java:
public Map<Double,Double> berechneWerteTabelle(float[] koeffizienten, int von, int bis, double schrittGroesse) {
}
 

AndiE

Top Contributor
Wir reden hier aneinander vorbei. Angenommen, ich habe eine Funktion y= 2x+3, dann kann ich im bereich -10 bis +10 werte für x festlegen, für die ich y bestimme. beides zusammen gibt Wertepaare, die ich in einer Wertetabelle auschreibe, z.B.((-10;-15);(-9;-15)...). Hierbei ist die Schrittweite "1", und ich erhalte 21 Wertepaare. Soweit verstanden? Probiert das einfach mal in einem neuen Projekt.
 

JStein52

Top Contributor
Ich kenne ja die Basisklassen von BlueJ zum Anzeigen und zeichnen nicht. Aber warum wollte ihr da mit einer Wertetabelle rumhantieren ? Mit einem JPanel würde ich das wie folgt lösen:
Ihr lest zuerst wie von @Tobse gesagt die Koeffizienten des Polynoms ein und noch den Wertebereich für den ihr das Polynom zeichnen wollt. Mit diesen Daten erzeugt ihr euch ein Objekt einer Klasse, nennen wir sie PolyPlot
Code:
public class PolyPlot extends JPanel {

    double[] coeff = null;
    double xMin = 0.0;
    double xMax = 0.0;

    public PolyPlot(double[] coeff, double xMin, double xMax) {
        super();
        this.coeff = coeff;
        this.xMax = xMax;
        this.xMin = xMin;
    }

    double f(double x) {
        // diese Funktion rechnet für beliebige X-Werte das zugehörige y aus.
        //
        // y(x) = coeff[0]*x^0 + coeff[1]*x^1 + coeff[2]*x^2 ... + coeff[n]*x^n   wobei n = coeff.length-1 ist
        double sum = 0.0;
        for (int i = 0; i < coeff.length; i++) {
            sum += coeff[i] * Math.pow(x, i);
        }
        return sum;
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // Achsen zeichnen, das muss man noch abhängig von der Fenstergrösse machen
        // hier sind feste Werte eingestellt
        g.drawLine(10, 100, 380, 100);
        g.drawLine(200, 30, 200, 190);

        // Pfeile an den Achsen
        g.drawLine(380, 100, 370, 90);
        g.drawLine(380, 100, 370, 110);
        g.drawLine(200, 30, 190, 40);
        g.drawLine(200, 30, 210, 40);

        g.drawString("X", 360, 80);
        g.drawString("Y", 220, 40);

        Polygon p = new Polygon();

        // hier Maximum und Minimum der Funktion innerhalb des Wertebereiches ausrechnen
        // zwengs der Skalierung
        // .......
        double scaleX = 1.0;  // hier den richtigen Faktor fuer X-Richtung
        double scaleY = 1.0;  // hier den richtigen Faktor fuer Y-Richtung

        for (int x = 10; x <= 380; x++) {  // fuer jeden Punkt auf der x-Achse
            p.addPoint(x, (int) (scaleY * f((x * scaleX))));
        }

        g.setColor(Color.red);
        g.drawPolyline(p.xpoints, p.ypoints, p.npoints);

        g.drawString("" + xMin, 10, 115);
        g.drawString("" + xMax, 380, 115);

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        double[] coeff = {3.5, 0.0, 0.0, 0.0, 0.0}; // diese Werte müssen vom Benutzer eingegeben werden

        JFrame myFrame = new JFrame("PolyPlot");
        myFrame.setLayout(new BorderLayout());
        myFrame.add(new PolyPlot(coeff, 20.0, 40.0), BorderLayout.CENTER); xMin und xMax müssen vom Benutzer eingegeben werden
        myFrame.setResizable(true);
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            // closes all windows
        myFrame.setSize(500, 300);
        myFrame.setVisible(true);
    }
}
diese Klasse zeichnet per paintComponent den Graphen der Funktion und ruft dabei zum Berechnen von f(x) die Methode gleichen Namens auf die den Wert des Polynoms berechnet.

Im Beispiel oben sind die Achsen und deren Position sowie die Pfeile und Beschriftungen mit fester Länge und Position eingezeichnet. Das müsst ihr noch anpassen und ihr müsst auch die Skalierungsfaktoren in x- und y-Richtung noch korrekt ausrechnen. Der Code ist als Demo gedacht was ihr tun müsst ... und ich weiss auch nicht wie ihr mit euren Klassen zeichnet (ist das auch ein JPanel ??)

Ich weiss schon, die Puristen werden sagen die Funktionswerte werden dazu ja alle zweimal berechnet, einmal zur Skalierung und einmal zum Zeichnen. Aber what shall's ....
 

AndiE

Top Contributor
Sorry, aber mir ist das zu viel auf einmal. Vom Logischen Vorgehen her würde ich erst ein Array aus Funktionswerten erzeugen und dieses dann anzeigen lassen. Ich habe dann auch die Trennung zwischen Anzeige und Verarbeitung, die dem MVC-Model schon nahe kommt. Ich finde, so ein schrittweises Vorgehen hat einen höheren Lerneffekt beim TE.
 

mrBrown

Super-Moderator
Mitarbeiter
Ich habe dann auch die Trennung zwischen Anzeige und Verarbeitung, die dem MVC-Model schon nahe kommt.
Was man für MVC braucht ist nur eine Methode im Model, die einem die entsprechenden Werte liefert.

Ein Array aus Funktionswerten passend für die View zu berechnen, bricht eigentlich eher MVC :p
Die Wertetabelle ist ja nur zum Anzeigen (muss passende Skalierung, Wertebereich etc haben), aber kein Teil einer Funktion. Das oben ist aber natürlich auch kein MVC^^
 

AndiE

Top Contributor
Klar. Ich finde trotzde, eine Kapselung der Berechnung von der Anzeige gut. Das was berechnet wird ist in einer Klasse. Wie das angezeigt wird in einer anderen Klasse.
 

dbvh2000

Mitglied
@AndiE @Tobse @mrBrown @JStein52 Wir hatten wieder Informatik und unser Lehrer hat uns jetzt geholfen.
Ich habe einige Dateien dazu hochgeladen.
Auf einem Bild seht ihr, dass es noch Probleme gibt. Zum Beispiel kommt der Stift immer von unten und malt dabei schon eine Linie. Weiß jemand, wie man das behebt?
Außerdem fehlen noch Funktionen wie z.B. Zoomen etc. oder die Funktion, dass vorher abgefragt wird, wie hoch der Exponent ist und dann nacheinander die Werte eingegeben werden. Es kann also noch weiter optimiert werden :(

Info-Projekt2.png Info-Projekt1.jpg
 

Anhänge

  • Taschenrechner-Projekt Daniel und Valentin.zip
    39,5 KB · Aufrufe: 1
  • basisUTF8151112.jar
    270,1 KB · Aufrufe: 5
  • Info-Projekt.txt
    23,3 KB · Aufrufe: 3

JStein52

Top Contributor
Hallo, habt ihr euch mal ausgeben lassen wo der Stift nach dieser Operation steht ?
Code:
                stift2.hoch();
                stift2.bewegeBis(Min+240,275-a*Min*Min*Min*Min*Min+b*Min*Min*Min*Min+c*Min*Min*Min+d*Min*Min+e*Min+f);
                stift2.runter();
Vermutlich steht ihr da am Ausgangspunkt der ersten (unerwünschten) Linie oder ?
Und ihr zeichnet in einem Koordinatensystem das der Grösse eurer Leinwand entspricht (in Pixeln vermute ich mal).
Um darin richtig zu zeichnen solltet ihr abfragen in welchem Wertebereich die Funktion gezeichnet werden soll (z.B. x=-10 ... x=+2 ) wozu dann ein bestimmter Wertebereich in y-Richtung gehört den ihr euch ausrechnen könnt/müsst. Und dann braucht ihr einfach eine richtige Skalierung von diesen Werten auf die entsprechenden Pixel-Werte. Und Zoomen heisst dann einfach ihr ändert den Wertebereich z.B.auf -0.5 ... +0.5

Edit: und die Skalierung ist dann einfach ein Dreisatz. x = -10 ... +10 ist zum Beispiel 20, d.h. einem RealWorld-Bereich von 20 entsprechen z.B. 400 Pixel (eure Fensterbreite in Pixel). welcher Wertebereich entspricht dann 1 Pixel ? Um diesen Betrag musst ihr dann immer das Argument beim Berechnen von f(x) erhöhen um so schrittweise für jedes Pixel einen y-Wert zu berechnen.
 
Zuletzt bearbeitet:

Neue Themen


Oben