Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 20 von 21

Thema: Wurzle Problem

  1. #1

    Users Awaiting Email Confirmation

    Wurzle Problem

    hallo, ich habe mal wieder ein noob problem:
    ich wollte eigentlich bloß eine Wurzelfunktion erstellen:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int Global=0;
    
    const double PI=3.141592653;
    
    #define BR cout<<'\n';
    
    double Wurzel(int a, double b=0);
    
    int main(void)
    {
       cin>>Global;
       Wurzel(Global);
       BR
       
       cin>>Global;
       return 0;
    }
    double Wurzel(int a, double b)
    {
       while(b*b<a)
       {
          cout<<"b*b ist: "<<b*b;
          BR
          cout<<"a ist : "<<a;
          BR
          if(!(b*b<a))cout<<"b*b ist nicht kleiner als a\n";
          b+=0.001;
          cout<<b;
          BR
       }
       return b;
    }
    Jedoch wenn ich ich im Prog dann 4 eingebe kommt am Ende 2.001 raus, könnte das tzwar umgehen, aber wo liegt der Fehler?

  2. #2
    Wieso benutzt du nicht einfach die eingebaute Wurzel-Funktion? Oder wenigstens einen vernuenftigen Algorithmus, und nicht Bruteforce?

  3. #3

    Users Awaiting Email Confirmation

    wusste zwar nicht das es eine Wurzel Funktiojn ist, aber ich wollte esja eh als Übung machen und was Bruteforce ist weiß ich noch nicht, bin noch Anfänger, aber uhrsprünglich war das Programm so, also ohne die Verschönerung, wenn du das meinst:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int Global=0;
    
    const double PI=3.141592653;
    
    #define BR cout<<'\n';
    
    double Wurzel(int a, double b=0);
    
    int main(void)
    {
       cin>>Global;
       cout<<Wurzel(Global);
       BR
       
       cin>>Global;
       return 0;
    }
    double Wurzel(int a, double b)
    {
       while(b*b<a)
       {
          b+=0.001;
       }
       return b;
    }
    Was da passiert?
    Ich gebe eine 4 ein und als Wurzel bekomme ich 2.001 zurück.
    Das was ich in dem anderem eingegeben habe sollte nur zeigen das bei b*b 4 am Ende rauskommt und a 4ist aber dass b*b kleiner als a scheint, was nach meiner Logik sehr seltsam ist oder?

  4. #4
    Afaik(kenn mich mit Fließkommazahlen nicht aus) liegt das daran, dass du double benutzt, ohne Nachkommastelle wird eine Fließkommazahl iirc in einen Integer umgewandelt.

    Wieso hast du eigentlich b als Parameter? oO

  5. #5

    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

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

  7. #7

    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!

  8. #8
    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.

  9. #9

    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

  10. #10
    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  

  11. #11

    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.

  12. #12
    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.

  13. #13

    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!

  14. #14
    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.

  15. #15
    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.

  16. #16

    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

  17. #17
    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.

  18. #18
    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.

  19. #19

    Users Awaiting Email Confirmation

    Na ja, kann ja sein das Compiler das verschieden sehen, aber so falsch kann dieser Code doch nicht sein, das mann ihn nicht compilieren kann
    Außerdem funktioniert end1 bei mir nicht, was ich zwar schon versucht habe allerdings nicht geklappt hat.

  20. #20
    endl (ENDL) und nicht end1 (END1) für End Line

Berechtigungen

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