Funktion umstellen oder Nullstelle berechnen



  • Ich hab die Funktion:

    radius = B * R^3 + (1 - 😎 * R

    Wie kann ich die umstelen zu

    R = f(radius) ??? Das will mir nicht gelingen.

    **************************************************************************
    Oder wenigstens für einen speziellen Wert auflösen:

    radius = rmax = B * R^3 + (1 - 😎 * R oder

    B * R^3 + (1 - 😎 * R - rmax = 0

    wie kann bei letzter Gleichung die Nullstelle berechnet werden?

    Gegeben sind:
    B : 0.0 < B < 1.0
    rmax : 1.0 < rmax < unendlich

    Hoffe jemand bringt das besser als ich.

    Gruss
    Frank



  • Hilfreich beim Programmieren:
    ZUERST Hirn einschalten!



  • Ich bin nicht mehr besonders gut in Mathe, aber letztens brauchte ich die Cardanischen Formeln - passt das?



  • Also solche Gleichungen dritten Grades kann man für gewöhnlich nicht genau lösen, d.h. du kannst sie auch nicht einfach nach R umformenen.

    Wenn dir das mit den cardanischen Formeln nicht so zusagt, kannst du dir auch eine Funktion schreiben, die dieNullstelle näherungsweise ermittelt(z.B. Newton-Verfahren), diese konvergieren meistens sehr schnell und du kannst dir die Nullstelle bis zu einer beliebigen Genauigkeit ermitteln (z.B. bis zur 5. Nachkommastelle, je nach dem, wie genau du sie brauchst).
    Solch eine Funktion ist auch nicht schwer zu implementieren.



  • Edit:
    Noch was: Wenn du bei ein solcher Funktion eine Lösung kennst, kannst du die restlichen (es gibt ja maximal 3) per Polynomdivision berechnen, also:

    (B * R^3 + (1 - 😎 * R - radius) / (R - 1.Nullstelle) = ...



  • Powerpaule schrieb:

    Also solche Gleichungen dritten Grades kann man für gewöhnlich nicht genau lösen, d.h. du kannst sie auch nicht einfach nach R umformenen.

    Ich glaube in diesem speziellen Fall geht's durch 0.0 < B < 1.0 und 1.0 < rmax < unendlich .
    Nach den Cardanischen Formeln wäre die Diskriminante D=radius24B2(1B)327B3D = \frac{radius^2}{4B^2} - \frac{(1-B)^3}{27B^3}. Durch 4B2<27B34B^2 < 27B^3 und radius2>1radius^2>1 und (1B)3<1(1-B)^3 < 1 müsste die Diskriminante immer positiv sein.

    Nach den C.F. gibt's dann genau eine reelle Lösung mit R = \sqrt[3]{ -\frac{q}{2} + \sqrt[2]{D}}~~+~~\sqrt[3]{ -\frac{q}{2} - \sqrt[2]{D}} 🙂



  • Suuuuuper,
    der Tip von Badestrand hats gebracht. 🙂 🙂 🙂

    Es liegt tatsächlich nur der eine Spezielfall vor, wie angenommen. Für die anderen Fälle mach ich sowieso ne ganz andere Berechnung (ohne Nullstelle).

    Ich komme zwar bei Determinate auf PLUS für den zweiten Term, aber das Ergebnis passt! Stimmt genau mit meiner Näherungsrechnung überein.

    So ists aber besser (schneller), da nicht angenähert werden muss.

    Thx
    Frank 🙂 🙂 🙂

    PS:
    Wen es interessiert: Das ist für die Berechnung der Linsenkorrektur nach Prof. Dersch in einem Graphik- Tool (einfache Form mit nur B!=0).



  • Sicher, dass das so genauer ist? Wurzeln werden im Rechner ja auch nur mit Newton- bzw. Heronverfahren gelöst, oder irre ich mich?

    Dann wäre ein direktes Newtonverfahren doch vermutlich besser weil keine Hintereinanderschaltung…



  • .filmor schrieb:

    Sicher, dass das so genauer ist? Wurzeln werden im Rechner ja auch nur mit Newton- bzw. Heronverfahren gelöst, oder irre ich mich?

    Dann wäre ein direktes Newtonverfahren doch vermutlich besser weil keine Hintereinanderschaltung…

    So, ich hab mal einen Test programmiert:

    //Das ist mit Näherungsverfahren
    //1 Mio mal berechnen!

    int Count=1000000;
      int ImgW,ImgH;
      double RMax,D,ROrgMax,R,RO,RU,ROrg,V;
      double B=0.2;
      D=1.0 - B;
      //vorhandenes Kissen entzerren
      ImgW=2288;
      ImgH=1712;
      while (Count>0)
      {
        RMax=double(max(ImgW,ImgH)) / double(min(ImgW,ImgH));
        RO=RMax;
        RU=0;
        R=RO;
        ROrg=(B * R * R  + D) * R;
        while (fabs(ROrg - RMax)>0.0001)
    //    while (fabs(ROrg - RMax)>0.0000000000001)
        { if (ROrg>RMax)
          { RO=R;
            R=(R + RU) / 2.0;
          }
          else
          { RU=R;
            R=(R + RO) / 2.0;
          }
          ROrg=(B * R * R + D) * R;
        }
        V=R  / RMax;
        Count--;
      }
    

    //Das ist mit "direkter" Berechnung
    //1 Mio mal berechnen!

    int Count=1000000;
      int ImgW,ImgH;
      double RMax,D,ROrgMax,R,RO,RU,ROrg,V;
      double Det,SqrtDet,Det1,Det2;
      double B=0.2;
      D=1.0 - B;
      //vorhandenes Kissen entzerren
      ImgW=2288;
      ImgH=1712;
      while (Count>0)
      {
        RMax=double(max(ImgW,ImgH)) / double(min(ImgW,ImgH));
        Det=(RMax * RMax) / (4 * B * B) + (D * D * D) / (27 * B * B * B);
        if (Det>0)
        {
          SqrtDet=sqrt(Det);
          Det1=RMax / (2 * B) + SqrtDet;
          Det2=RMax / (2 * B) - SqrtDet;
          if (Det1>0)
          { Det1=pow(Det1,(1.0 / 3.0));
          }
          else
          { Det1=-pow(-Det1,(1.0 / 3.0));
          }
          if (Det2>0)
          { Det2=pow(Det2,(1.0 / 3.0));
          }
          else
          { Det2=-pow(-Det2,(1.0 / 3.0));
          }
          R=Det1 + Det2;
          V=R  / RMax;
        }
        else
        { break;
        }
        Count--;
      }
    

    Ergebnis:
    1. Genauigkeit kann (fast) gleich sein.
    (wird Tolleranzschwelle bei "Suche" minimal gemacht, ist Ergebnis
    bis auf 15.te Stelle gleich)
    2. "Annäherung" ist bei maximaler Genauigkeit halb so schnell
    3. "Annäherung" ist bei Genauigkeit ca. 5 Stelle doppelt so schnell

    Fazit:
    - Für hochgenaue Berechnungen ist direkter Weg besser (schneller)
    - Für begrenzte Genauigkeit ist Annäherung besser (schneller aber "ungenau")

    Hinweis:
    - getestet auf Borland BCB
    - Datentypen alle double !!!

    beide Teile können sicher noch optimiert werden!

    Gruss und Dank
    Frank


Anmelden zum Antworten