Funktions-Plotter - Division durch 0 vermeiden

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Funktions-Plotter - Division durch 0 vermeiden

    Hi. Ich möchte eine Funktion z=f(x,y) ausgeben. Der Benutzer gibt die Funktionsgleichung und den Bereich (z.b.: x € [-1;1], y € [-1;1]) an. Nun gibt es ja bekanntlich Funktionen wie z.B. 1/x, bei denen es eine Division durch 0 gäbe. Wenn dieses Problem auftritt, dann bricht das Skript ab. Wie kann ich das verhindern?

    Hier noch ein bisschen Code:
    PHP-Code:
    $f="exp(\$y)/\$x";
    $funktion="\$z=".$f.";";
    for(
    x=...){
     for(
    y=...){
      eval(
    $funktion);
     }

    andreas.mkq.de

  • #2
    ein einfacher IF?

    PHP-Code:
    if($x == 0) {
    echo 
    "fehler"
    } else {
    //deine funktion

    tutorial: peterkropff.de schattenbaum.de tut.php-quake.net
    documentation: php.net mysql.com framework.zend.com

    Die Nachtwache!

    Kommentar


    • #3
      wenn du die funktion per eval() auswertest, weißt du nicht, was dort im nenner steht (hint: richtiges funktionsparsing ist nicht schwierig zu realisieren). eine if-abfrage (wenn du weißt, was der nenner ist) kann zu schweren performanz-problemen führen (z.b. def. bereich [-1000;1000]x[-1000;1000]). eine exception wird bei php hier nicht geworfen, dafür "nur" ein warning. d.h. du könntest einen error-handler schreiben, der das warning abarbeitet.

      andererseits ist 1/x für x=0 wirklich nicht definiert, d.h. für das zeichnen wird einfach kein punkt eingetragen. d.h. u.u. ist es auch ausreichend, das warning einfach zu unterdrücken.

      Kommentar


      • #4
        Das 1/x war ja nur eine Beispielfunktion. Ein anderes Beispiel wäre: f=1/(x-1)... Die ist bei x=1 nicht definiert... Und da meine Funktion ja nur als String vorliegt (wird aus einem Formular ausgelesen) ist das nicht so einfach.
        Ich denke, man müsste irgendwie den Fehler, der in eval() auftritt "abfangen". Wenn ein Fehler auftritt, dann an der Stelle nichts zeichnen, aber weitermachen. Nur wie geht das?
        Zuletzt geändert von el muesli; 28.03.2007, 12:30.
        andreas.mkq.de

        Kommentar


        • #5
          @penicillin: danke. warning unterdrücken klingt gut. ich guck mal, wie ich das mache... und an "richtiges funktionsparsing" hab ich mich noch nicht rangetraut.
          beste grüße
          andreas.mkq.de

          Kommentar


          • #6
            Hi,

            genau genommen ist der angegeben definitionsbereich dann
            kein definitionsbereich. Denn für einige elemente des definitionsbereichs
            ist die geg. funktion nicht definiert. Das aber widerspricht gerade
            der definition des definitionsbereich.

            Eine möglichkeit wäre einfach folgendes zu machen:

            Sei f die zu berechnende gebrochenrationale funktion.
            Sei Dx der vermutete definitionsbereich des nennerpolynoms.
            Sei X0 die menge aller nullstellen des nennerpolynoms.
            Dann ist der tatsächliche definitionsbereich Dt defintiert durch
            Dx \ X0 also gerade der differenzmenge von Dx u. X0.


            greets
            Zuletzt geändert von closure; 28.03.2007, 13:12.
            (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

            Kommentar


            • #7
              closure, vollkommen richtig, eigentlich sollte man die funktion erst richtig parsen, um die nullstellen zu bestimmen und sie aus dem "zeichenbereich" auszuschließen, um den def.-bereich zu bestimmen. das geht sogar iterativ ganz gut, ohne sich analytisch mit der funktion auseinanderzusetzen.

              Kommentar


              • #8
                Hi,

                ich weis ja nicht mit welcher art funktion du da arbeitest,
                aber unsere überlegungen beziehen sich nur auf den sonderfall
                der undefinierten division durch 0 in R.
                Es gibt natürlich noch andere fälle bei denen lücken auftreten können.
                Nur der vollständigkeit halber.

                greets
                (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

                Kommentar


                • #9
                  Es geht um alle Funktionen f:R²->R, die man mit einer "einfachen" Regel definieren kann (also keine Sprungfunktionen oder sowas). Der Benutzer gibt die Funktion an. Deshalb kanns auch vorkommen, dass sie nicht im gesamten zu plottenden Bereich definiert ist... Und wie ich jetzt automatisiert Nullstellen eines Polynoms rauskriegen soll (welches ich noch nichtmal kenne - ohne Funktionsparsing) weiß ich auch nicht. Per Hand oder zur Not mit Maple kann ich das . Aber in PHP? Das würde den Rahmen sprengen, denke ich.
                  Ich hab keine Ahnung von error-handling.
                  Ich würde ja gern sowas erreichen:
                  PHP-Code:
                  eval($funktion);
                  if(
                  ERROR:division durch null
                  ->
                  zeichne nix oder ne senkrechte gerade durch (x,yoder mache irgendwas anderes
                  else ->zeichne Punkt (x,y,z
                  andreas.mkq.de

                  Kommentar


                  • #10
                    Hi,

                    du hast das problem ja erkannt.
                    Nun musst du dich nur noch hinsetzen und einen parser
                    für diese art funktionen schreiben

                    greets
                    (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

                    Kommentar


                    • #11
                      Ich weiß nicht... Selbst schreiben ist unnötig aufwändig. Es geht ja auch schon mit Fehler-ignorieren...
                      Aber zu meiner letzten Frage bzgl. error-handling kannst du mir keinen Tipp geben? Ich behaupte das wäre die ökonomischste Lösung...
                      andreas.mkq.de

                      Kommentar


                      • #12
                        hi,

                        naja warnings können mit dem shutup-operator unterdrückt
                        werden. Ich bin mir im moment nicht sicher ob das auch für eval
                        gilt, sollte aber.

                        greets
                        (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

                        Kommentar


                        • #13
                          Es geht um alle Funktionen f:R²->R, die man mit einer "einfachen" Regel definieren kann (also keine Sprungfunktionen oder sowas).
                          closure meint u.a. sowas wie ist log(x-1), das ist für x=1 nicht definitert (und die nullstelle bei 2 hilft auch nicht unbedingt weiter).
                          Und wie ich jetzt automatisiert Nullstellen eines Polynoms rauskriegen soll
                          durch approximation, z.b. durch das (vereinfachte) newton-verfahren. allerdings benötigt man dafür die ableitung, wo wir wieder beim parsing wären. da brauchst du aber das rad nicht neu zu erfinden, musst nur schauen, wie andere das lösen (natürlich auch in anderen sprachen). google mal nach "polynom/function parsing", "diffentiation" und "derivation".
                          Ich hab keine Ahnung von error-handling.
                          Ich würde ja gern sowas erreichen:
                          1. wie immer gilt: rtfm und google.
                          2. du könntest ("für lau") folgendes erreichen:
                          PHP-Code:
                          wenn(warning tritt auf){
                             
                          # mach irgendwas (oder auch nichts)
                          }
                          eval(
                          fkt); #schmeißt u.u. ein warning, ist aber nicht schlimm. 

                          Kommentar


                          • #14
                            Irgendwie glaube ich, dass wir abdriften... Ich kenne mich auch ganz gut mit Numerik aus, und ich behaupte, dass wir für mein Problem nun wirklich keine numerischen Approximationen benötigen.
                            Es geht einzig und allein darum, ob eval() eine Fehler "ausspuckt" oder nicht. Wie ich abfragen kann, ob ein Fehler (Warnung) beim Aufruf der Funktion aufgetreten ist weiß ich leider nicht. aus dem php.net-manual werde ich nicht schlau. bei den neueren php-versionen scheint eval() werte zurückzugeben - also wahrscheinlich auch aufgetretene fehler.
                            schluss für heute. danke
                            andreas.mkq.de

                            Kommentar


                            • #15
                              Hi,

                              eine unsaubere aber funktionierende geschichte wäre:

                              PHP-Code:
                              $result null;
                              if(@eval(
                              "\$result = 1/0;")){
                                  
                              //zeichne
                              }//else es wurde false zurück gegeben 
                              greets
                              (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

                              Kommentar

                              Lädt...
                              X