kostenloser Webspace werbefrei: lima-city


Gleichung erstellen

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    c*************h

    Ja, ich habe da so ein Problem und da würde ich gerne wissen, wie erstelle ich eine Gleichung, die durch ein =-Zeichen getrennt ist, aber jetzt nicht einfach so was hier ist: 4+4=8
    Sondern sowas: 4*(4-8)²+65=-223,5*2
    Wie kann ich sowas erstellen, als Zufallsgenerator????
    Wenn das Niemand wissen sollte kann man mir auch gerne erst einmal einen Zufallsgenerator für Gleichungen wie: 4+4=8 geben!!!
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Hallo carl-schoeneich,

    die längere Gleichung ist gar keine sondern (Quotientenmengen mal ausgeschlossen) schlicht falsch.
    Das '=-' ist ja eigentlich auch kein Zeichen sondern ein '=' gefolgt von einer negativen Zahl.
    Wenn Du einen mathematische Ausdruck (nur die linke oder rechte Seite) per Zufallsgenerator erzeugen willst, dann geht das wie folgt:
    Als erstes musst Du die erlaubten mathematischen Operationen mit Zahlen assoziieren. Z.B. folgendermaßen:
    1 => +
    2 => -
    3 => *
    4 => /
    5 => Potenzieren (x^y)

    Als zweites benötigst Du einen binären Baum dessen Elemente entweder eine mathematische Operation (innerer Knoten) oder eine Zahl (Blatt) darstellen.
    Jetzt kannst Du wie folgt vorgehen:
    1. Erzeuge eine ganzzahlige Zufallszahl zwischen 1 und 5
    2. Füge die zugehörige Operation in den Baum ein.
    3. Erzeuge eine ganzzahlige Zufallszahl zwischen 1 und 2 für den ersten Kindknoten
    4. Wenn die Zufallszahl 1 ist, dann für den ersten Kindknoten weiter bei (1.)
       sonst erzeuge eine Zahl und füge sie ein.
    5. Erzeuge eine ganzzahlige Zufallszahl zwischen 1 und 2 für den zweiten Kindknoten
    6. Wenn die Zufallszahl 1 ist, dann für den zweiten Kindknoten weiter bei (1.)
       sonst erzeuge eine Zahl und füge sie ein.
    Wenn alle Kindknoten mit Zahlen besetzt sind, dann ist man fertig. Man sollte aber ab einer bestimmten Baumtiefe das setzen von Zahlen erzwingen, d.h. (3) und (5) werden nicht durchgeführt und nur noch eine Zufallszahl erzeugt, damit das nicht ewig weitergeht.
    Am Ende hat man dann z.B. sowas:
    .               +
         ___________|___________
        |                       |
        *                       ^
     ___|___                 ___|___
    |       |               |       |
    8       +               3       2
         ___|___
        |       |
        3       4
    Diesen Daum kann man jetzt der Reihe nach in eine Formel umbauen, indem man rekursiv absteigt bis man bei einem Blatt (Zahl) ist und dann Schritt für Schritt wieder aufsteigt.
    Zusammengesetzt kommt dann (Klammern gemäß Operatorpräzedenz einfügen) folgendes raus:
    8*(3+4)+3^2

    Edit: Hier habe ich noch etwas Beispiel-Code für Binary-Trees in PHP gefunden:
    http://www.zend.com//code/codex.php?ozid=539&single=1

    Beitrag zuletzt geändert: 9.3.2012 22:31:43 von darkpandemic
  4. Autor dieses Themas

    c*************h

    Ja, danke für diese sehr ausführliche Erklärung!!!
    Mal sehen, wie sich das umsetzen lässt!!! :wink:

    Doch, mein eigentlich größtes Problem ist, wie erstelle ich dann zu dieser Seite der Gleichung die andere Seite, die den Gleichen Wert hat????

    Beitrag zuletzt geändert: 10.3.2012 8:40:02 von carl-schoeneich
  5. Hallo carl-schoeneich,

    ich habe mir mal erlaubt die Sache ein wenig anzuprogrammieren:
    <?php
    
    class Operation
    {
      const Add = 0;
      const Sub = 1;
      const Mul = 2;
      const Div = 3;
      const Pow = 4;
      const MaxIndex = 4;
    }
    
    class Node
    {
      public $firstChild = NULL;
      public $secondChild = NULL;
      public $value = 0;
      
      function isOperator()
      {
        return !is_null($this->firstChild) && !is_null($this->secondChild);
      }
      
      function getValue()
      {
        if($this->isOperator())
        {
          switch($this->value)
          {
            case Operation::Add:
              return $this->firstChild->getValue() 
                + $this->secondChild->getValue();
            case Operation::Sub:
              return $this->firstChild->getValue() 
                - $this->secondChild->getValue();
            case Operation::Mul:
              return $this->firstChild->getValue() 
                * $this->secondChild->getValue();
            case Operation::Div:
            return $this->firstChild->getValue() 
              / $this->secondChild->getValue();
            case Operation::Pow:
              return pow( $this->firstChild->getValue(),
                    $this->secondChild->getValue());
            default;
              return 0;
            
          }
        }
        else
        {
          return $this->value;
        }
      }
      
      function getString()
      {
        if($this->isOperator())
        {
          switch($this->value)
          {
            case Operation::Add:
            {
              $text = $this->firstChild->getString();
              
              if($this->secondChild->isOperator())
              {
                $text .= "+(" . $this->secondChild->getString() . ")";
              }
              else if($this->secondChild->value < 0)
              {
                $text .= $this->secondChild->getString();
              }
              else
              {
                $text .= "+" . $this->secondChild->getString();
              }
              
              return $text;
            }
            case Operation::Sub:
            {
              $text = $this->firstChild->getString();
              
              if($this->secondChild->isOperator())
              {
                $text .= "-(" . $this->secondChild->getString() . ")";
              }
              else if($this->secondChild->value < 0)
              {
                $text .= "+" . (-$this->secondChild->getValue());
              }
              else
              {
                $text .= "-" . $this->secondChild->getString();
              }
              
              return $text;
            }
            case Operation::Mul:
            {
              $text = "";
              
              if( $this->firstChild->isOperator() || 
                $this->firstChild->value < 0)
              {
                $text .= "(" . $this->firstChild->getString() . ")";
              }
              else
              {
                $text .= $this->firstChild->getString();
              }
              
              $text .= "*";
              
              if( $this->secondChild->isOperator() || 
                $this->secondChild->value < 0)
              {
                $text .= "(" . $this->secondChild->getString() . ")";
              }
              else
              {
                $text .= $this->secondChild->getString();
              }
              
              return $text;
            }
            case Operation::Div:
            {
              $text = "";
              
              if( $this->firstChild->isOperator() || 
                $this->firstChild->value < 0)
              {
                $text .= "(" . $this->firstChild->getString() . ")";
              }
              else
              {
                $text .= $this->firstChild->getString();
              }
              
              $text .= "/";
              
              if( $this->secondChild->isOperator() || 
                $this->secondChild->value < 0)
              {
                $text .= "(" . $this->secondChild->getString() . ")";
              }
              else
              {
                $text .= $this->secondChild->getString();
              }
              
              return $text;
            }
            case Operation::Pow:
            {
              $text = "";
              
              if( $this->firstChild->isOperator() || 
                $this->firstChild->value < 0)
              {
                $text .= "(" . $this->firstChild->getString() . ")";
              }
              else
              {
                $text .= $this->firstChild->getString();
              }
              
              $text .= "^";
              
              if( $this->secondChild->isOperator() || 
                $this->secondChild->value < 0)
              {
                $text .= "(" . $this->secondChild->getString() . ")";
              }
              else
              {
                $text .= $this->secondChild->getString();
              }
              
              return $text;
            }
            default;
              return 0;
            
          }
        }
        else
        {
          return $this->value;
        }
      }
    }
    
    function buildTreeRecursion($maxDepth)
    {
      $node = new Node();
      if($maxDepth > 0 && rand(0,1) == 0)
      {
        $node->firstChild = buildTreeRecursion($maxDepth-1);
        $node->secondChild = buildTreeRecursion($maxDepth-1);
        $node->value = rand(0,Operation::MaxIndex);
      }
      else
      {
        $node->value = rand(-20, 20);
      }
      
      return $node;
    }
    
    function buildTree($maxDepth)
    {
      $tree = new Node();
      $tree->value = rand(0,Operation::MaxIndex);
      $tree->firstChild = buildTreeRecursion($maxDepth-1);
      $tree->secondChild = buildTreeRecursion($maxDepth-1);
      return $tree;
    }
    
    srand();
    $tree = buildTree(3);
    echo $tree->getString(). "=" . $tree->getValue();
    
    ?>
    Und mir ist dabei auch noch eingefallen, wie Du die zweite Seite bekommen kannst.
    Du kannst den Wurzelknoten standardmäßig auf eine Addition setzen. Dann hast Du als Ergebnis ja immer etwas von der Form
    <linker Teilbaum> + <rechter Teilbaum>
    Andererseits kannst Du ja den gesamten Baum berechnen lassen, d.h. Du weißt was insgesamt herauskommt. Dann kannst Du die Sache einfach umstellen zu:
    <linker Teilbaum> = <Gesamtergebnis> - (<rechter Teilbaum>)
    Und schon hast Du was Du willst ;-)
  6. Autor dieses Themas

    c*************h

    Danke!!!
    Das klappt alles super!!!
    Aber kann man das auch noch irgendwie begrenzen, dass das Ergebnis nicht über 10000 sein sollte, oder so???
    Wäre sehr hilfreich!!!

    Aber nochmal schonmal VIELEN DANK!!!!!!
  7. Hallo carl-schoeneich,

    das einfachste Vorgehen um das Ergebnis einzuschränken besteht darin, einfach einen neuen Baum zu generieren wenn der aktuelle außerhalb des gewünschten Intervalles liegt.
    Allerdings kann kann man auch vorab schon die erlaubten Divisoren und Exponenten einschränken, damit allzu große Werte unwahrscheinlicher werden (und damit kein NAN/INF vorkommt):
    function buildTreeRecursion($maxDepth)
    {
      $node = new Node();
      if($maxDepth > 0 && rand(0,2) != 0)
      {
        $node->value = rand(0,Operation::MaxIndex);
        
        if($node->value == Operation::Div)
        {
          $node->firstChild = buildTreeRecursion($maxDepth-1);
          do
          {
            $node->secondChild = buildTreeRecursion($maxDepth-1);
          }while(abs($node->secondChild->getValue()) < 0.0001);
        }
        else if($node->value == Operation::Pow)
        {
          do
          {
            $node->firstChild = buildTreeRecursion($maxDepth-1);
          }while($node->firstChild->getValue() < 0);
          
          do
          {
            $node->secondChild = buildTreeRecursion($maxDepth-1);
          }while(abs($node->secondChild->getValue()) > 5);
        }
        else
        {
          $node->firstChild = buildTreeRecursion($maxDepth-1);
          $node->secondChild = buildTreeRecursion($maxDepth-1);
        }
        
        
      }
      else
      {
        $node->value = rand(-20, 20);
      }
      
      return $node;
    }
    
    function buildTree($maxDepth)
    {
      $tree = new Node();
      do
      {
        $tree->value = 0;
        $tree->firstChild = buildTreeRecursion($maxDepth-1);
        $tree->secondChild = buildTreeRecursion($maxDepth-1);
      } while(abs($tree->getValue()) > 10000);
      
      return $tree;
    }
    
    $tree = buildTree(4);
    
    echo $tree->getString() . "=" . $tree->getValue() ."<br/>";
    echo $tree->firstChild->getString() . "=";
    echo $tree->getValue() . "-(";
    echo $tree->secondChild->getString(). ")";
    Zusätzlich habe ich noch an der Wahrscheinlichkeit zum Setzen einer Zahl gedreht, damit man interessantere Ergebnisse bekommt.
    In der Node-Klasse sind im übrigen noch zwei kleine Vertipper: In den switch-Anweisungen gehört nach 'default' ein ':' (Doppelpunkt) und kein ';' (Strichpunkt).
  8. Autor dieses Themas

    c*************h

    Wo soll ich das jetzt einsetzen?????
    Aber sonst vielen Dank, damit müsste dann alles klappen!!!!
  9. Hallo carl-schoeneich,

    die Klassen 'Operation' und 'Node' läßt Du wie sie sind.
    Die bisherigen Funktionen 'function buildTree($maxDepth)' und 'function buildTreeRecursion($maxDepth)' löscht Du raus und kopierst dafür die geänderten Versionen rein.
    Die letzen 6 Zeilen erzeugen nur eine Beispielausgabe, die sind nicht wichtig.
  10. Autor dieses Themas

    c*************h

    OK, danke!!!!!!!!
    Funktioniert alles wie geplant!:wink:

    Nur noch eins, wie kann ich das endgültige Ergebnis der Gleichung dann ausgeben??
    Also dann, dass beide Seiten diesen Wert haben???
    Also einfach nur -6 oder so?

    Beitrag zuletzt geändert: 16.3.2012 20:06:44 von carl-schoeneich
  11. Hallo carl-schoeneich,

    wenn Du die Gleichung nach dem Schema
    <linker Teilbaum> = <Gesamtergebnis>-(<rechter Teilbaum>)
    ausgibst, dann ist der Wert der linken Seite der Gleichung gleich dem Wert des linken Teilbaumes. (Linker Teilbaum soll der erste Kinknoten = firstChild sein).
    Diesen bekommst Du mit
    $leftValue = $tree->firstChild->getValue();
    Die Knoten sind ja so gemacht, dass man mit getValue() den numerischen Wert und mit getString() den mathematischen Ausdruck bekommt. Die rechte Seite der Gleichung hat natürlich den gleichen Wert. Wenn man es explizit gegengerechnet haben will, dann kann man das wie folgt berechnen:
    $rightValue = $tree->getValue() - $tree->secondChild->getValue();

  12. Autor dieses Themas

    c*************h

    Danke!
    Damit funktioniert jetzt echt alles!!!! :prost:
  13. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!