Ergebnis 1 bis 20 von 21

Thema: Wurzle Problem

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1

    Users Awaiting Email Confirmation

    Dachte eigentlich auch du hättest recht, aber:
    Code:
    #include <iostream>
    
    using namespace std;
    
    double Global=0;
    
    const double PI=3.141592653;
    
    #define BR cout<<'\n';
    
    double Wurzel(double a, double b=0);
    
    int main(void)
    {
       cin>>Global;
       cout<<Wurzel(Global);
       BR
       
       cin>>Global;
       return 0;
    }
    double Wurzel(double a, double b)
    {
       while(a>b*b)
       {
          b+=0.001;
       }
       return b;
    }
    Anderer Code, gleiches Ergebnis

  2. #2
    Euch ist schon klar, das man so etwas normalerweise über Lookuptables und Interpolieren rechnet, oder?

  3. #3

    Users Awaiting Email Confirmation

    Nun, mir nicht bin aber auch noch Anfänger,aber es ist eh nur eine Übung, bei der ich aber nicht versteh weshalb das falsch läuft!

  4. #4
    Zitat Zitat von Tridestaros Beitrag anzeigen
    Nun, mir nicht bin aber auch noch Anfänger,aber es ist eh nur eine Übung, bei der ich aber nicht versteh weshalb das falsch läuft!
    Okay, ich hab' mich gerade hingesetzt und ein klein wenig gerechnet: Die Quadratwurzel sollte sich über das newtonsche Näherungsverfahren ermitteln lassen. Ich habe das ganze jetzt für den speziellen Fall aufgelöst und bin auf folgende Funktion gekommen:

    x_{n+1} = (x_{n} + z/x_{n})/2

    In dem Fall näherst du dich an die Wurzel von z an, wobei du mit n immer durch iterierst. Soll heißen: Du rechnest dir erst immer x_{0} aus, dann x_{1}, usw. Bis das Ergebnis deiner Meinung nach genau genug ist.


    Warum das nicht verwendet wird, siehst du hier auch recht gut: Das ganze ist eine Reihe und somit wird immer wieder das Selbe neu ermittelt. Je nach Zahl und Fall muss auch immer besser angenähert werden. Dadurch braucht das ganze erstens immer recht viel Zeit, und zweitens auch immer je nach Genauigkeit wieder länger, oder eben nich.

    Darum löst man das normalerweise eben über eine Lookup-Table: Hier habe ich schlichtweg eine Liste, die vom kleinstmöglichen Wert, bis zum größtmöglichen Wert in vielen Unterschritten die Wurzel bereits ausgerechnet. Wenn ich jetzt zum Beispiel die Wurzel von 1 wissen will, dann suche ich in der Liste das passende Ergebnis. Wenn ich jetzt aber die Wurzel aus 1.2 haben will, und dieser Wert ist nicht in der Liste, dann suche ich mir die beiden Werte heraus,z wischen denen diese Zahl steht. Sagen wir einmal, es sind 1 und 2.

    Laut unserer Liste wissen wir also, das unser Ergebnis zwischen 1 und 1.41421 liegen muss. Darum interpolieren wir zwischen den beiden Werten. Um an ein möglichst genaues Ergebnis finden zu können, überlegen wir uns einmal, wie eine Wurzel-Funktion aussieht:
    http://www.mathematik.net/wurzel-fkt/WF1S10P4.gif

    Jetzt suchen wir uns also eine Funktion, die dieser Kurve recht nahe kommt. Wir machen es uns einfach und interpolieren einfach linear: Wir rechnen uns also die Steigung aus, verlagern geistig die Axen und ermitteln den Punkt auf dem ca die gewollte Wurzel liegt. Und schon haben wir es geschafft.




    Da du programmieren lernen willst, gebe ich dir noch einen Tipp:
    #define BR cout<<'\n';

    Verwende so etwas niemals. Verwende den Praeprozessor nur dann, wenn es sein muss. Also, wenn du zum Beispiel zwischen Versionen unterscheiden willst, oder etwas dergleichen. Wenn deine Projekte einen gewissen Umfang übersteigen, dann wirst du bemerken, das ein großer Teil der Compile-Time vom Praeprozessor verbraucht wird.
    Außerdem macht das den ganzen Source unübersichtlich. Verwende lieber Konstante Werte, inline-Funktionen, etc.

  5. #5

    Users Awaiting Email Confirmation

    ok, dein Vortrag, klang ziemlich wissenschaftlich, x_{n+1} = (x_{n} + z/x_{n})/2, habe ich ehrlich gesagt nicht verstanden, weil x_{n+1} mir nicht sagt was das x ist und was das{}ist, aber ich denke ich habe verstanden was du mit der schnelleren Wurzelfunktion meinst, nämlich das die groben Werte schon vorgegeben sind.
    Auch das mit define habe ich eingesehen, aber jetzt noch zwei Fragen:
    1. Wie benutzt man dann diese schon vorgegebene Wurzelfunktion?
    2. Weshalb wird dann der Code von mir( auch wenn er nur bei kleineren Zahlen geeignet ist ) falsch gewertet, also dass bei Wurzel aus 4 2.001 rauskommt? Anscheinend scheint er ja b*b=4 und a=4 ja nicht als gleich anzusehen.

    @Mog:
    Sry, das ich deine x_{n+1} = (x_{n} + z/x_{n})/2
    Funktion nicht verstandfen habe, aber eigentlich habe ich ne 2+ in Matte

  6. #6
    Zitat Zitat von Tridestaros Beitrag anzeigen
    ok, dein Vortrag, klang ziemlich wissenschaftlich, x_{n+1} = (x_{n} + z/x_{n})/2, habe ich ehrlich gesagt nicht verstanden, weil x_{n+1} mir nicht sagt was das x ist und was das{}ist, aber ich denke ich habe verstanden was du mit der schnelleren Wurzelfunktion meinst, nämlich das die groben Werte schon vorgegeben sind.
    Auch das mit define habe ich eingesehen, aber jetzt noch zwei Fragen:
    1. Wie benutzt man dann diese schon vorgegebene Wurzelfunktion?
    2. Weshalb wird dann der Code von mir( auch wenn er nur bei kleineren Zahlen geeignet ist ) falsch gewertet, also dass bei Wurzel aus 4 2.001 rauskommt? Anscheinend scheint er ja b*b=4 und a=4 ja nicht als gleich anzusehen.

    @Mog:
    Sry, das ich deine x_{n+1} = (x_{n} + z/x_{n})/2
    Funktion nicht verstandfen habe, aber eigentlich habe ich ne 2+ in Matte

    1)
    C: #include <math.h>, bzw. cmath in Cpp.

    double sqrt(double x)


    2) && @:
    Siehe was ich geschrieben habe, das ist eine ganz einfache Formel.

    X_{b} bedeutet eigentlich nur, das ein b nach dem X tief gestellt steht. Schau dir mal den Anhang an, so angeschrieben verstehst du es sicher.
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken Foo.png  

  7. #7

    Users Awaiting Email Confirmation

    ok, deine Funktion habe ich jetzt auch verstanden, aber immer noch mein Hauptproblem:
    Warum kommt eine höhere Zahl raus,(immer um 0.001)?
    Der code ist doch richtig, oder?
    Versucht doch sonstmal das Programm selbst zu compilieren.

  8. #8
    Zitat Zitat von Tridestaros Beitrag anzeigen
    ok, deine Funktion habe ich jetzt auch verstanden, aber immer noch mein Hauptproblem:
    Warum kommt eine höhere Zahl raus,(immer um 0.001)?
    Der code ist doch richtig, oder?
    Versucht doch sonstmal das Programm selbst zu compilieren.
    also ich hab das ganze mal auf meinem Rechner getestet. Also hier hab ich keine Probleme. Er berechnet alles so wie ers soll.

  9. #9

    Users Awaiting Email Confirmation

    Seltsam, bei mir gibt er jetzt bei einer 1 1.00 zurück, also den richtigen Wert.
    Aber gib mal 4 ein oder 100 und es kommt 2.001 oder 10.001 raus!

  10. #10
    Ich empfehle dir noch, b als Parameter herauszunehmen und innerhalb der Wurzelfunktion erst zu initialisieren, denn so wie es da steht macht es etwas wenig Sinn.

    Zu deinem Problem kann ich gar nichts sagen, da bei diesem Programm mein Compiler nur Fehlermeldungen ausspuckt.

  11. #11
    Zitat Zitat von Tridestaros Beitrag anzeigen
    Seltsam, bei mir gibt er jetzt bei einer 1 1.00 zurück, also den richtigen Wert.
    Aber gib mal 4 ein oder 100 und es kommt 2.001 oder 10.001 raus!
    Könnte noch am ehesten an der internen Darstellung der Zahl liegen. Da die Zahlenspeicherung ja zu Basis zwei funktioniert, kann das 0.001, das du bei jeder Schleife dazuzählst, nicht ganz genau gespeichert werden. Bei einem Mal würde man das nicht merken, aber da bei der Berechnung der Wurzel aus 2 der Wert ja 2000 Mal addiert wird, ist die Iteration vor 2.001 wahrscheinlich nicht genau 2, sondern ganz knapp darunter. Dadurch wäre b² natürlich auch unter 4, und die Schleife würde erst bei der nächsten Iteration abbrechen.

    Das eheste, was du dagegen tun könntest, wäre, 0.001 z.B. durch 0,0009765625 zu ersetzen, das ist 1/1024 und sollte dadurch, glaube ich, genau darstellbar sein. Allerdings würde es dann bei nicht-ganzen Wurzeln natürlich weiterhin zu Fehlern kommen.

  12. #12

    Users Awaiting Email Confirmation

    @drunken monkey:

    Es geht tatsächlich!!!!
    ok, dann nehme ich ab nun nur noch durch 2^x teilbare Zahlen für so was!
    Hier noch mal was am Ende dabei rauskommt:
    Code:
    #include <iostream>
    
    using namespace std;
    
    double Global=0;
    
    const double PI=3.141592653;
    
    void BR()
    {
       cout<<'\n';
    }
    double Wurzel(double a, double b=0);
    
    int main(void)
    {
       cin>>Global;
       cout<<Wurzel(Global);
       BR();
       
       cin>>Global;
       return 0;
    }
    double Wurzel(double a, double b)
    {
       while(a>b*b)
       {
          b+=0.0009765625;
       }
       return b;
    }
    @TheBiber:
    Das müsste aber eigentlich gehen, ist ein C++ Projekt
    Mfg Tridestaros

  13. #13
    Zitat Zitat von Tridestaros Beitrag anzeigen
    @TheBiber:
    Das müsste aber eigentlich gehen, ist ein C++ Projekt
    Mfg Tridestaros
    *lacht* Du wirst dich in Zukunft noch oft wundern.

  14. #14
    Zitat Zitat von Tridestaros Beitrag anzeigen
    @TheBiber:
    Das müsste aber eigentlich gehen, ist ein C++ Projekt
    Mfg Tridestaros
    Daß C++ theoretisch portabel ist bedeutet nicht, daß auch beliebiger Code überall läuft. Besonders von Windows-Usern geschriebene Tutorials und Bücher verweisen gerne auf Windows-spezifische Header wie <conio.h> und selbst harmlos erscheinende Ausdrücke erweisen sich als fast(!) überall gebräuchliche aber letztendlich nicht ISO-konforme Erweiterungen.

    Dazu kommen noch unterschiedliche Compiler... Was dir der Visual C++-Compiler durchgehen läßt kann GCC 3.3 unter Cygwin dazu bringen, dich mit Warnungen zu überfluten - und GCC 4 für Linux bricht gleich mit einer Fehlermeldung ab, von Apples GCC-Version für OS X ganz zu schweigen. Oder von --pedantic.

    Wenn du willst, daß dein Code überall läuft, mußt du schon aufpassen, was du schreibst und möglichst portable Bibliotheken verwenden (und im Idealfall auf mehreren Plattformen testen). C++ ist in dieser Hinsicht nicht gerade die einfachste Sprache, dafür hat man extrem viele Möglichkeiten.


    BTW, deine BR()-Funktion ist ziemlich häßlich. Du wirst weit besser damit fahren, wenn du stattdessen einfach an das letzte cout ein << endl anhängst. Das ist nicht nur lesbarer sondern auch schneller, da der Compiler solche Funktionen nicht immer wegoptimiert und jeder einzelne Funktionsaufruf Zeit kostet.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •