Generate Cubic Polynomial for given solution

  • C#
  • .NET (FX) 4.0

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Generate Cubic Polynomial for given solution

    Hi,

    Ich experimentiere gerade etwas mit dem lösen/generieren kubischer Gleichungen, d.h. Gleichungen der Form.
    $ax^3+bx^2+cx+d=0$

    Gehen wir davon aus ich wähle eine beliebige Zahl
    $x$
    zwischen Int32.MinValue und Int32.MaxValue.
    Ich möchte dazu eine kubische Gleichung, bzw die Koeffizienten
    $a$
    ,
    $b$
    $c$
    und
    $d$
    finden, sodass die reelle Lösung der Gleichung meine gewählte Zahl
    $x$
    ist. (Komplexe Lösungen werden nicht betrachtet)
    Eine kubische Gleichung kann aber meines Wissens nach zwei Fälle haben, 1 reelle Lösung oder 3.
    Ich möchte
    $a$
    ,
    $b$
    $c$
    und
    $d$
    so finden das folgende Kriterien erfüllt sind:
    1. Die Gleichung hat meine Gewählte Zahl als reelle Lösung.
    2. $a$
      ,
      $b$
      $c$
      und
      $d$
      dürfen den Wertebereich eines Int32's nicht überschreiten (Int32-Minvalue bis Int32.MaxValue)
    3. Ist zuvor genanntes auch möglich wenn ich zusätzlich noch einen der Werte
      $a$
      ,
      $b$
      $c$
      oder
      $d$
      konstant wähle?
    Gibt es dafür einen mathematisch intelligenten Ansatz?
    C# Developer
    Learning C++

    Rikudo schrieb:

    Eine kubische Gleichung kann aber meines Wissens nach zwei Fälle haben, 1 reelle Lösung oder 3.
    1 2 oder 3.
    Die zweier hat einen Schnittpunkt mit und eine Tangente an die x-Achse.
    Gibt es nicht ein Schema zur Lösung kubischer Gleichungen?
    Du kannst Dich auf jeden Fall per Automat von außen nach innen antasten, und solange die Funktionswerte links und rechts verschiedene Vorzeichen haben, halbierst Du das Intervall usw., bis Du nahe genug dran bist.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Rikudo nimm x1 und x2 so, dass y(x1) ein anderes Vorzeichen hat als y(x2).
    Das garantiert, dass zwischen ihnen (mindestens) eine Nullstelle vorkommt.
    Nun machst Du x1' = (x1 + x2) / 2
    Wenn das Vorzeichen der y-Werte verschieden ist, x1 := x1', ansonsten: x2 := x1'.
    und immer so weiter, bis x2 - x1 < Epsilon.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Rikudo
    y = x ^ 3, 3-fache Nullstelle bei x = 0.
    Da wir das wissen, machen wir den Rand unsymmetrisch.
    x0 = -1.1 => y = -1.331
    x1 = 0.9 => y = 0.729
    x' = -0.1 => y = -0.001
    => x0 := x' = -0.1 ( => y = -0.001 )
    x' = 0.4 => y = 0.064
    => x1 = x' = 0.4
    x' = 0.15 => y = 0.003375
    => x1 = x' = 0.15
    usw.
    Du musst natürlich auch einen Null-Test und einen Epsilon-Test einbauen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Was für mich aus Deiner Ursprungsfrage noch ungeklärt ist: Woher kommt x? Ist x zwingend reell? Oder kann es auch komplex sein? Du spezifizierst zwar x als Integer-Wert, aber dann wäre es halt speziell ganzzahlig. ^^ Also Du deckst halt nicht alle reellen Zahlen ab. Ist das gewollt?

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    @Trade
    $x$
    ist eine reelle Zahl, ja. Ich betrachte die complexen Zahlen hier nicht.
    Also ich möchte quasi einen reellen Wert vorgeben, sowie einen der Parameter
    $a$
    ,
    $b$
    ,
    $c$
    oder
    $d$
    .
    Die generierte Gleichung kann entweder (Fall1) eine reelles Ergebnis haben, welches in diesem Fall dann
    $x$
    sein muss, oder (Fall2) drei reelle Werte, dann muss einer davon
    $x$
    sein.
    Außerdem ist wichtig das keiner der Parameter
    $a$
    ,
    $b$
    ,
    $c$
    oder
    $d$
    den Int32 Wertebereich überschreitet.
    Zusätzlich soll das ganze für jedes
    $x$
    zwischen Int32.MinValue bis Int32.MaxValue funktionieren.
    Bin mir sicher da gibts irgendwelche cleveren mathematischen Tricks :D
    C# Developer
    Learning C++

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Rikudo“ ()

    Trade schrieb:

    Ist x zwingend reell?
    Ich sags nicht gern, aber das steht doch da:

    Rikudo schrieb:

    Die Gleichung hat meine Gewählte Zahl als reelle Lösung.
    und @Rikudo Gugst Du Regula Falsi.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Ich kann immer noch nicht ganz folgen..
    Also ich versuche jetzt quasi mir eine Funktion auszudenken und dann via Näherungsverfahren Nullstellen zu überprüfen? Das ist ja das was der Wikipedia Artikel zu Regula Fasi beschreibt.
    C# Developer
    Learning C++

    Rikudo schrieb:

    das
    Meinst Du meinen Nicht-Code?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Rikudo Na aber.
    Das ist doch nun wirklich so elementar einfach, dass Du das selbst hinkriegen solltest.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    @Rikudo Na aber.
    Das ist doch nun wirklich so elementar einfach, dass Du das selbst hinkriegen solltest.

    Ich habe mich schlecht ausgegedrückt.
    Das programmieren an sich ist wahrscheinlich ein Kinderspiel aber ich durchsteige immer noch nicht die Mathematik deines Verfahrens..
    C# Developer
    Learning C++
    @RodFromGermany @Trade Ich habe mich nochmal auf ein paar Matheboards erkundigt was die beste herangehensweise für mein Problem ist.
    Ich habe jetzt einen Ansatz aber ich bin mir nicht so sicher wie ich das in C# umsetzen soll.

    Wenn ich eine Gleichung der Form
    $a*x^3+b*x^2+c*x+d=0$
    lösen möchte wobei
    $a$
    vorgegeben ist und eine
    reelle Lösung der kubischen Funktion eine bestimmte Zahl sein soll kann man das wie folgt umschreiben:
    $x^3+b*x^2+c*x+d=x^3+(B−r)x^2+(C−B*r)x−C*r $

    Dabei gibt es folgende Vorgaben:

    $a=1$
    (Möchte man einen anderen Koeffizienten kann man ja einfach die Gleichung multiplizieren.)
    $B$
    kann beliebig gewählt werden.
    $C$
    kann beliebig gewählt werden.
    $r$
    ist meine gewünschte reelle Lösung der kubischen Gleichung.

    Danach kann man die Gleichung für
    $b$
    ,
    $c$
    und
    $d$
    lösen.
    Keine Ahnung wie ich das in C# gescheit machen soll, ich habe mal ein Beispiel mithilfe von Wolfram Alpha generiert:

    Ziel: Eine Gleichung der Form $
    $a*x^3+b*x^2+c*x+d$
    finden die als reelle Lösung
    $r=123$
    hat. Für
    $a$
    wähle ich
    $50$
    . Nun kann ich
    $B$
    und
    $C$
    beliebig wählen, sagen wir
    $B=10$
    und
    $C=20$
    .
    Setzen wir nun die Werte in die obige Gleichung um unsere Koeffizienten
    $b$
    ,
    $c$
    und
    $d$
    zu finden. :
    $x^3+b*x^2+c*x+d=x^3+(10−123)x^2+(20−10*123)x−20*123$


    Wolfram Alpha findet folgende Werte für die Koeffizienten:
    $b=-113$

    $c=-1210$

    $d=-2460$


    Damit habe ich meine gewünschte kubische Gleichung:
    $x^3-113*x2-1210x-2460=0$

    Und wenn man das auflöst hat man als reelle Lösung
    $123$
    :)

    Schön und gut, dabei gibt es aber noch zwei kleine Probleme:
    1) Ich habe keine Ahnung wie ich dafür sorgen kann das jeder der Koeffizienten im Int32 Bereich bleibt.
    2) Ich habe keine Ahnung wie ich das in C# implementieren soll.

    In Python habe ichs hinbekommen, aber auch nur mit einem Solver.
    Ich würde das in C# gerne ohne eine externe lib machen.

    C-Quellcode

    1. from random import randint
    2. import sympy
    3. from sympy.abc import b,c,d,B,C,r,x
    4. # Set values of choice
    5. B, C, r = 10, 20, 123
    6. # Equation: x^3+b*x^2+c*x+d=x^3+(B−r)x^2+(C−B*r)x−C*r
    7. equation = sympy.Eq(x**3+b*x**2+c*x+d,x**3+(B-r)*x**2+(C-B*r)*x-C*r)
    8. # Solve equation to find coefficients
    9. coefficents = sympy.solve(equation, "b,c,d", dict=True)
    10. # Parse results
    11. b1 = [sol[b] for sol in coefficents][0]
    12. c1 = [sol[c] for sol in coefficents][0]
    13. d1 = [sol[d] for sol in coefficents][0]
    14. # Print as equation
    15. print(f"x^3+{b1}x^2+{c1}x+{d1}=0")



    Vorschläge? :/
    C# Developer
    Learning C++

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Rikudo“ ()

    @Rikudo Das mit dem vorgegebenen Wertebereich der Koeffizienten ist mir durch die Lappen gegangen.
    Das würde ich zunächst nicht so eng sehen, sondern erst, wenn die Lösungen da sind.
    Und dann kannst Du ja die gesamte Kurve "skalieren", sodass diese Bedingung wieder erfüllt ist.
    ====
    Mit folgendem Verfahren finde ich das kommunizierende Minimum einer beliebigen Funktion f(x).
    Soll heißen: Eine komplizierte Funktion habe mehrere Minima.
    Ich wähle ein beliebiges x aus und finde das Minimum, wo eine Kugel hin rollt, wenn sie auf dem x der Funktion abgesetzt wird:
    yA = f(x - delta)
    yB = f(x)
    yC = f(x + delta)
    wobei delta so gewählt ist, dass kein fernes Minimum gefunden werden kann.
    Durch diese 3 Punkte legst Du eine Parabel, deren Minimum Du per Schema F bestimmst.
    Dieses Minimum ist das neue x.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!