Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Konvertierung von Excel -> PHP

Einklappen

Neue Werbung 2019

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

  • [Erledigt] Konvertierung von Excel -> PHP

    Hallo zusammen,

    ich bin dabei ein Excel-Blatt in PHP zu konvertieren und komme schonmal damit nicht klar, dass man sich in den Excel-Formeln ganz leicht auf bestimmte Zellen beziehen kann, auch wenn die Formel in einer Zelle vor der Deklaration steht. In PHP geht das ja nicht so einfach, weil man dann eine "Undefined variable..." Meldung bekommt.

    Hinzu kommt, dass Excel ja standardmäßig automatisch iteriert und so habe ich in Excel Formeln, die sich querverweisen und Excel so lange arbeitet, bis irgendwann ein errechneter Wert in einer Zelle steht.

    Hier mangelt es mir an der Umsetzung in php.

    Code:
    A = 1110
    B = 370
    C = 6171.6
    D = (C-J) // Muss "5629,476" ausgeben
    E = (I-B/1000)*A/100 // Muss "42,6475454545455" ausgeben
    F = I*A/100 // Muss "46,7545454545455" ausgeben
    G = H/(545.223880597015/1000*L*K) // Aufrundung ohne Komma, muss "132" ausgeben
    H = 71.1
    I = 556/G // Muss "4,21212121212121" ausgeben
    J = G*B/1000*A/100*1 // Muss "542,124" ausgeben
    K = function get_factor_K(I) // I wird benötigt. Gibt in diesem Beispiel "0,9942" aus
    L = function get_factor_L(I) // I wird benötigt. Gibt in diesem Beispiel "0,998670248976177" aus
    Weiß jemand, wie ich die Berechnungen in php umschreiben könnte?

    Danke.
    Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.


  • #2
    Indem du die Berechnungen in die richtige Reihenfolge bringst? Du kannst zB nicht schon bei D ein C-J rechnen wollen, denn J ist zu dem Zeitpunkt noch gar nicht bekannt.

    Oder ich habe dich falsch verstanden.
    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
    PHP.de Wissenssammlung | Kein Support per PN

    Kommentar


    • #3
      Hallo,

      das ist mir schon klar. Das Problem ist aber, dass ich es nur bis einem bestimmten Punkt in richtiger Reihenfolge bringen kann. Z.B. ist ab dem Buchstaben G Ende. Denn für G brauche ich später dann auch I + K + L (diese wieder miteinander querverweisen sind).

      Danke.


      //Edit

      Hier mal etwas anders sortiert:

      PHP-Code:
      <?php
      $A 
      1110;
      $B 370;
      $C 6171.6;
      $H 71.1;
      $I 556/$G// Muss "4,21212121212121" ausgeben
      $K get_factor_K($I); // I wird benötigt. Gibt in diesem Beispiel "0,9942" aus
      $L get_factor_L($I); // I wird benötigt. Gibt in diesem Beispiel "0,998670248976177" aus
      $G $H/(545.223880597015/1000*$L*$K); // Aufrundung ohne Komma, muss "132" ausgeben
      $J $G*$B/1000*$A/100*1// Muss "542,124" ausgeben
      $D = ($C-$J); // Muss "5629,476" ausgeben
      $E = ($I-$B/1000)*$A/100// Muss "42,6475454545455" ausgeben
      $F $I*$A/100// Muss "46,7545454545455" ausgeben


      echo 'A: '.$A;
      echo 
      '<br />';
      echo 
      'B: '.$B;
      echo 
      '<br />';
      echo 
      'C: '.$C;
      echo 
      '<br />';
      echo 
      'D: '.$D;
      echo 
      '<br />';
      echo 
      'E: '.$E;
      echo 
      '<br />';
      echo 
      'F: '.$F;
      echo 
      '<br />';
      echo 
      'G: '.$G;
      echo 
      '<br />';
      echo 
      'H: '.$H;
      echo 
      '<br />';
      echo 
      'I: '.$I;
      echo 
      '<br />';
      echo 
      'J: '.$J;
      echo 
      '<br />';
      echo 
      'K: '.$K;
      echo 
      '<br />';
      echo 
      'L: '.$L;
      echo 
      '<br />';

      function 
      get_factor_K($I)
      {
          return 
      0.9942;
      }

      function 
      get_factor_L($I)
      {
          return 
      0.998670248976177;
      }

      ?>
      Notice: Undefined variable: G in test.php on line 6

      Warning: Division by zero in test.php on line 6
      Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

      Kommentar


      • #4
        Örks. Was ist das denn?

        PHP-Code:
        function get_factor_K($I)
        {
            return 
        0.9942;
        }

        function 
        get_factor_L($I)
        {
            return 
        0.998670248976177;

        Hängt das nun von $i ab oder nicht?

        Kommentar


        • #5
          Dem undefined kannst du entgegenwirken, in dem du die/alle Vars vorher initialisierts.

          Hingegen das ...

          PHP-Code:
          $I 556/$G// Muss "4,21212121212121" ausgeben
          $K get_factor_K($I); // I wird benötigt. Gibt in diesem Beispiel "0,9942" aus
          $L get_factor_L($I); // I wird benötigt. Gibt in diesem Beispiel "0,998670248976177" aus
          $G $H/(545.223880597015/1000*$L*$K); // Aufrundung ohne Komma, muss "132" ausgeben 
          ... wird spannend das aufzulösen, wenn G das L und K braucht, und K und L das I, das I aber wiedeerrum das G.

          Und wozu die beiden Fuktionen, die geben ja fixe Werte zurück, also sinnlos?

          LG
          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
          PHP.de Wissenssammlung | Kein Support per PN

          Kommentar


          • #6
            Hallo ihr zwei,

            hinter den beiden Funktionen steckt eine komplexe Berechnung. Diese sind für die Problemlösung aber irrelevant, darum habe ich die fixe Werte hingeschrieben, die nach der Berechnung ausgegeben werden sollten. Ich habe das nur zu eurer Verdeutlichung mit aufgenommen. Sorry, falls ich euch damit irritiert habe.

            Danke.

            //Edit
            Für den Fall der Fälle, dass ihr euch obere Codes zur Analyse kopiert haben solltest: Ich habe folgendes oben geändert (kleiner Fehler bei der Übertragung... sorry):

            H zu I geändert:
            Code:
            E = (H-B/1000)*A/100 // Muss "42,6475454545455" ausgeben
            F = H*A/100 // Muss "46,7545454545455" ausgeben
            in
            Code:
            E = (I-B/1000)*A/100 // Muss "42,6475454545455" ausgeben
            F = I*A/100 // Muss "46,7545454545455" ausgeben
            geändert.
            Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

            Kommentar


            • #7
              Hi

              Zitat von hausl Beitrag anzeigen
              ... wird spannend das aufzulösen, wenn G das L und K braucht, und K und L das I, das I aber wiedeerrum das G.
              Und genau das ist mein Problem und der Grund von diesem Thread. Ich weiß einfach nicht weiter...

              Danke.
              Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

              Kommentar


              • #8
                Wenn $k und $l als konstant angesehen werden können, dann löst sich die Problematik auf, dass $i dazu benötigt wird, um $i zu berechnen. Dann ist es wirklich nur eine Frage der Reihenfolge.

                Den komplizierteren Ansatz, $i auszurechnen, habe ich jetzt aber dringelassen.

                PHP-Code:
                <?php

                // $A = 1110;
                // $B = 370;
                // $C = 6171.6;
                // $H = 71.1;
                // $I = 556/$G; // Muss "4,21212121212121" ausgeben
                // $K = get_factor_K($I); // I wird benötigt. Gibt in diesem Beispiel "0,9942" aus
                // $L = get_factor_L($I); // I wird benötigt. Gibt in diesem Beispiel "0,998670248976177" aus
                // $G = $H/(545.223880597015/1000*$L*$K); // Aufrundung ohne Komma, muss "132" ausgeben
                // $J = $G*$B/1000*$A/100*1; // Muss "542,124" ausgeben
                // $D = ($C-$J); // Muss "5629,476" ausgeben
                // $E = ($I-$B/1000)*$A/100; // Muss "42,6475454545455" ausgeben
                // $F = $I*$A/100; // Muss "46,7545454545455" ausgeben


                function get_factor_k($i)
                {
                    
                // Replace with correct code
                    #return $i;
                    
                return 0.9942;
                }

                function 
                get_factor_l($i)
                {
                    
                // Replace with correct code
                    #return $i;
                    
                return 0.998670248976177;
                }

                $a 1110;
                $b 370;
                $c 6171.6;

                $h 71.1;

                $i 0.001// undef
                $k 0;     // undef
                $l 0;     // undef

                $step 0.001;    // Auflösung für $i
                $i_max 100;     // um keine Endlosschleife zu produzieren
                $epsilon 0.001// Fehlertoleranz
                $found false;

                do {
                    
                $k get_factor_k($i);
                    
                $l get_factor_l($i);
                    
                $tmp = (556 / ($h / (545.223880597015 1000 $k $l)));

                    
                $found = (abs($i $tmp) <= $epsilon);

                    if (!
                $found) {
                        
                $i += $step;
                    }

                    if (
                $i $i_max) {
                        throw new 
                Exception('Unable to calculate $i');
                    }
                } while (!
                $found);



                $g ceil($h / (545.223880597015 1000 $l $k));

                $i 556 $g// ??? $i haben wir schon

                $j $g $b 1000 $a 100 1;

                $e = ($i $b 1000) * $a 100;
                $f $i $a 100;

                $d $c $j;

                foreach (
                range('a''l') as $var) {
                    echo 
                $var ' = ';
                    
                var_dump($$var);
                }

                Kommentar


                • #9
                  Hallo,

                  das ist echt spitze von dir

                  Ich muss jetzt mal testen, ob mir das für diverse Szenarios ausreicht.

                  Ich melde mich wieder.

                  Danke!
                  Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

                  Kommentar


                  • #10
                    Allgemein ist das wohl die Suche nach dem (angenäherten) Schnittpunkt zweier Funktionen.

                    Edit: Kleines Update.

                    PHP-Code:
                    <?php

                    /**
                     * Tries to find the first intersection of functions $f and $g within a given
                     * interval
                     *
                     * $discardExceptions allows $f and $g to reject/skip certain values (e. g.
                     * because of division by zero) by throwing an exception without having to stop
                     * the whole calculation.
                     *
                     * In theory, all intersections in the interval could be returned, not just the
                     * first one. But I couldn't be bothered to figure out whether the next
                     * intersection really is a *new* intersection and what to do when $f and $g
                     * have the same definition.
                     *
                     * @param Closure $f
                     * @param Closure $g
                     * @param int|float $from
                     * @param int|float $to
                     * @param int|float $step
                     * @param int|float $epsilon
                     * @param bool $discardExceptions
                     * @return array
                     * @throws InvalidArgumentException
                     * @throws Exception
                     */
                    function findIntersection(Closure $fClosure $g$from$to$step$epsilon 0.00001$discardExceptions true)
                    {
                        
                    $info = new ReflectionFunction($f);
                        if (
                    $info->getNumberOfParameters() !== 1) {
                            throw new 
                    InvalidArgumentException('$f must accept exactly one parameter');
                        }

                        
                    $info = new ReflectionFunction($g);
                        if (
                    $info->getNumberOfParameters() !== 1) {
                            throw new 
                    InvalidArgumentException('$g must accept exactly one parameter');
                        }

                        if (!
                    is_int($from) && !is_float($from)) {
                            throw new 
                    InvalidArgumentException('$from must be int|float');
                        }

                        if (!
                    is_int($to) && !is_float($to)) {
                            throw new 
                    InvalidArgumentException('$to must be int|float');
                        }

                        if (!
                    is_int($step) && !is_float($step)) {
                            throw new 
                    InvalidArgumentException('$step must be int|float');
                        }

                        if ((float) 
                    $step === 0.0) {
                            throw new 
                    InvalidArgumentException('$step cannot be 0');
                        }

                        if (
                            
                    $from $to && $step 0
                            
                    || $from $to && $step 0
                        
                    ) {
                            throw new 
                    InvalidArgumentException('Stepping in the wrong direction');
                        }

                        if (!
                    is_int($epsilon) && !is_float($epsilon)) {
                            throw new 
                    InvalidArgumentException('$epsilon must be int|float');
                        }

                        if (!
                    is_bool($discardExceptions)) {
                            throw new 
                    InvalidArgumentException('$discardExceptions must be bool');
                        }

                        
                    $ignoreActiveIteration false;

                        
                    $tmpf 0;
                        
                    $tmpg 0;

                        
                    $intersections = array();

                        
                    $x = (float) $from;

                        do {
                            try {
                                
                    $tmpf $f($x);
                                
                    $tmpg $g($x);
                            } catch (
                    Exception $e) {
                                if (
                    $discardExceptions) {
                                    
                    $ignoreActiveIteration true;
                                } else {
                                    throw 
                    $e;
                                }
                            }

                            if (
                    $ignoreActiveIteration) {
                                
                    // reset for next iteration
                                
                    $ignoreActiveIteration false;
                            } elseif (
                    abs($tmpf $tmpg) <= $epsilon) {
                                
                    $intersections[] = $x;
                                break;
                            }

                            
                    $x += $step;

                            if (
                    $x $to) {
                                break;
                            }
                        } while (
                    true);

                        return 
                    $intersections;
                    }

                    $f = function ($x) { return pow($x2) - 1; };
                    $g = function ($x) { return sin($x);        };

                    var_dump(findIntersection($f$g, -220.0010.001));

                    // http://www.wolframalpha.com/input/?i=x^2+-1+%3D+sin+x

                    // array(1) {
                    //   [0]=>
                    //   float(-0.63700000000011)
                    // }
                    - http://www.wolframalpha.com/input/?i=x^2+-1+%3D+sin+x

                    Kommentar


                    • #11
                      Hi mermshaus,

                      danke dafür. Deine erste Lösung fand ich leichter zu verstehen. Bei deiner zweiten Lösung verstehe ich noch nicht so richtig, wie ich es anwenden muss.

                      Ich habe übrigens noch nicht vergessen dir mitzuteilen, ob die erste Lösung soweit passt. Ich bin noch dabei diverse Szenarien durchzugehen. Das kann noch ein bisschen Zeit in Anspruch nehmen.

                      Gute Nacht.
                      Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

                      Kommentar


                      • #12
                        Gesucht ist eben eine Lösung für diese Gleichung, wobei $h bekannt ist und $i die Unbekannte ist.

                        Code:
                        $i == (556 / ($h / (545.223880597015 / 1000 * get_factor_k($i) * get_factor_l($i))));
                        Die rechte Seite kann man einfach als Funktion g($i) bezeichnen, die linke Seite als f($i). g() ist irgendeine Art von „Kurve“, wenn man es plotten würde, f() ist eine Gerade mit Steigung 1 durch den Ursprung. (f(x) = x halt.)

                        (Wie g() genau aussieht, weiß ich nicht, weil ich keine Ahnung habe, was die beiden get_factor-Funktionen für Werte liefern.)

                        Jedenfalls ist das dann so ähnlich wie hier: http://www.wolframalpha.com/input/?i=x+%3D+x^2+-1

                        Wenn du x – oder eben $i – ausrechnen willst, heißt das anschaulich, dass der Schnittpunkt gesucht ist.

                        PHP-Code:
                        $tmp findIntersection(
                            function (
                        $x) { return $x; },
                            function (
                        $x) use ($h) {
                                return (
                        556 / ($h / (545.223880597015 1000
                                               
                        get_factor_k($x) * get_factor_l($x)))); 
                            },
                            
                        $from$to$step$epsilon
                        );

                        if (
                        count($tmp) === 0) {
                            
                        // $i konnte nicht berechnet werden. Größeres Epsilon versuchen?
                        } else {
                            
                        $i $tmp[0];
                            
                        $k get_factor_k($i);
                            
                        $l get_factor_l($i);

                        Das war einfach ein Versuch von mir, den „tollen“ Algorithmus ein wenig mehr zu verallgemeinern.

                        Insgesamt ist das ja ohnehin nicht exakt, weil der Ansatz nur ausprobiert und nichts löst.

                        Das heißt, der Nutzen ist eher theoretisch.

                        Kommentar


                        • #13
                          Hallo mermshaus,

                          Gleichungen auflösen und Kurven-Themen etc, mochte ich schon damals zu Schulzeiten nicht. Damals dachte man immer, dass man sowas nie wieder im Leben benötigt. Tja, Pustekuchen

                          Danke für deine Erklärung!
                          Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

                          Kommentar


                          • #14
                            Hallo mermshaus,

                            ich hatte jetzt erst Zeit den zweiten Teil zu testen - unter der Woche habe ich keine Zeit dafür.
                            Wenn ich deinen zweiten Code versuche, dann errechnet er mir $i falsch. Statt "4.21212121212121" bekomme ich "4.2329999999997".

                            Ist das bei dir auch so, wenn du statt get_factor_k($i) "0.9942" und statt get_factor_l($i) "0.998670248976177" nimmst?

                            Danke.
                            Bis vor Kurzem hatte ich einen roten Bewertungspunkt. Leider kann ich nicht so ganz nachvollziehen warum das so war. Der Auslöser war diese harmlose Antwort, welches mit Kommentaren wie "was ein bullshit" bewertet wurde.

                            Kommentar


                            • #15
                              Also, sorry, wenn das bislang noch nicht stark genug durchgekommen ist. Ich dachte, das ist klar:

                              Mein Ansatz rechnet nichts exakt aus. Er rechnet f() und g() für verschiedene Testeingaben von x (bzw. $i) (innerhalb eines Intervalls mit einer Schrittweite) aus und guckt jeweils, ob die beiden Rückgabewerte der Funktionen sich um weniger unterscheiden als die angegebene Fehlertoleranz ($epsilon).

                              Wenn x = 1 ist und f(1) = 403.5 und g(1) = 410.2 und epsilon = 10, dann ist abs(403.5 - 410.2) <= epsilon und mein Ansatz liefert 1 als Rückgabewert, also als Fund.

                              Um ein besseres Resultat zu erhalten, müsstest du ein kleineres Epsilon wählen.

                              Nur: Wenn du Epsilon zu klein wählst, dann wird vielleicht überhaupt keine Lösung gefunden, da vielleicht nur bei x = 1.15 die beiden Funktionen einen Wert innerhalb der Fehlertoleranz liefern, dein Aufruf aber nur x=1.1 und x=1.2 ausprobiert, weil die Schrittweite auf 0.1 steht. Je verschiedener die Steigungen am Schnittpunkt, desto eher passiert das.

                              - Aber, ist das dann nicht ein ziemlich unbrauchbarer Ansatz?

                              Na ja, es ist ein recht trivialer und wenig exakter Ansatz. (Es hat schon seinen Grund, warum der Aufruf so viele Parameter als Stellschrauben hat.) Aber es ist ein Ansatz, der überhaupt mal so was wie eine halbwegs passende Lösung liefern kann.

                              Wenn weitere Aspekte des Problems bekannt sind („Es gibt immer genau einen Schnittpunkt, der immer zwischen a und b liegt.), lässt sich das Resultat noch algorithmisch verfeinern, weil du dann sagen kannst: „Ich bin jetzt bis auf $epsilon an der richtigen Stelle. Dann rufe ich den Algorithmus wieder auf, aber diesmal im Intervall $x-$epsilon bis $x+$epsilon und mit kleinerer Schrittweite und kleinerem Epsilon.“ Da wird es dann weniger trivial.

                              - Wie rechnet man das exakt aus?

                              Ihr stellt den Gesamt-Term auf, löst ihn nach x auf und baut das Ergebnis hartkodiert im Programmcode nach.

                              Wenn die get_factor-Funktionen immer konstante Werte liefern, die überhaupt nicht von x (oder $i) abhängen, ist das ja keine ganz große Kunst…

                              Kommentar

                              Lädt...
                              X