Cosinus



  • Hi,

    ich soll den Cosinus mit Java berechnen. Die Aufgabe kann man hier nachlesen:
    http://www.informatik.uni-freiburg.de/~asalm/cos.gif

    Irgendwie bekomm ich das nicht hin. Den zweiten Teil (das mit der Rekursion) versteh ich schonmal garnicht bzw. ich weiß nicht wo ich da anfangen soll. Aber das ist ja nicht so wichtig, es reicht auch wenn man es mit der ersten Formel macht.
    Da ist das Problem aber, dass n gegen unendlich geht. Wie mach ich sowas?
    Und selbst wenn ich nur bis zu einem kleinen Wert gehe, zB 200, gibt es Schwierigkeiten. In der Formel steht ja eine Fakultät, und 200! lässt sich bei weitem nicht mehr berechnen, selbst mit 64-Bit integern nicht.

    Könnt ihr mir da ein wenig weiterhelfen?



  • Dann geh doch für den Anfang mal nur so weit, daß Du die Fakultät noch berechnen kannst. Für große x ist das allerdings problematisch, da die Funktion dann nicht so schnell konvergiert. Aber da Du ja eh weißt, daß die Funktion 2Pi-periodisch ist könntest Du einfach so lange ganzzahlge vielfache von 2Pi abziehen, bis Du im Intervall [0,2Pi) bist und dann erst mit Deiner Berechnung anfangen. Dann müßte es auch genügen, wenn Du nur bis n=50 oder sogar n=20 vordringst.
    Außerdem mußt Du eh mit doubles oder sowas rechnen, weil das ja Kommawerte werden und die haben ne ziemliche Kapazität nach oben raus.
    MfG Jester



  • Da steht doch, dass der Cosiunus approximiert werden soll. Also eine endliche Anzahl an Gliedern.

    Und die untere Formel spart nur Rechenzeit, da das aktuelle Reihenglied Ri schnelller berechnet werden kann, wenn man den schon bekannten Ri-2 verwendet.



  • Dadurch sparst Du Dir dann auch das ständige berechnen der Fakultät.

    Du schaust einfach zwei zurück multiplizierst noch ein bissel dran rum (nix aufwendiges) und haust es dann mit auf die Summe drauf.

    MfG Jester



  • Hm schön und gut, wenn die zweite Version besser geht dann nehm ich die. Das Problem ist nur, dass ich die Mathe-Syntax nicht so richtig blick.
    Es steht ja dabei, dass i = 2k ist, aber was ist denn k?
    Und wo fange ich die Rekursion an? Wo hört sie dann auf?
    Wo setze ich den Wert ein, für den ich den cos haben will?

    Ein bisschen Pseudocode würde mir glaub ich sehr viel weiter helfen!

    Hm ich glaube ich muss meine Signatur mal überarbeiten, ist irgendwie peinlich 😉



  • Ich habe die Formel mal in meinen Taschenrechner eingegeben. Mit n=50 und x=1. Da kam dann -1.54308 raus.
    cos(1) ist aber 0.540302



  • Das ist dann wohl ein klarer Fall von Rechenungenauigkeit. Denn cos(x) \in [-1,1].

    MfG Jester



  • Das ist keine Rechenungenauigkeit. Das Ergebnis ist völlig falsch.
    Kann das mal jemand nachrechnen?



  • Das ist nicht völlig falsch, das ist um einen Offset verschoben. 😃

    @0x00000001
    Das untere ist keine 2te Methode sondern das sind die Reihenglieder anders ausgedrückt. Also alles Was in der obigen Formel rechts vom Summenzeichen steht kannst du auch dadurch ersetzen. Was das fürn k ist ist dann klar, ne ?



  • Ich hab das jetzt mit nem java Programm nachgerechnet.
    Da kommt dann tatsächlich das richtige Ergebnis raus (0.540302).

    public class Cosinus {
        public static void main(String[] args) {
            double r;
            double x=1;
            double cos=1;
    
            for(int n=1; n<=10; n++) {
                r=1;
                for(int k=n; k>0; k--) {
                    r*=x*x/((2*k-1)*2*k);
                }
                if(n%2 == 1) r*=-1;
                System.out.println("r"+(2*n)+" = "+r);
                cos+=r;
            }
    
            System.out.println("Cosinus = "+cos);
        }   
    }
    

    ich frage mich nur wieso mein Taschenrechner das nicht packt.
    Das ist ein Ti92+
    ich hab das so eingegeben (sum steht für das Summen Zeichen): sum(-1k*x(2*k)/(2*k)!,k,0,10)|x=1

    Um einen Offset verschoben ist es nicht. Es ist um 2.0833 verschoben.



  • DrZoidberg schrieb:

    sum(-1k*x(2*k)/(2*k)!,k,0,1,10)|x=1

    Hab zwar keine Ahnung vom TI92, aber mit sum((-1)k*x(2*k)/(2*k)!,k,0,1,10)|x=1 könnte da schon eher was sinnvolles herauskommen...



  • komisch. Ich dachte das negations zeichen (nicht das selbe wie das minus Zeichen) hätte eine höhere Priorität. Kenn mich mit dem rechner wohl doch noch nicht so gut aus.



  • DrZoidberg schrieb:

    Das ist keine Rechenungenauigkeit. Das Ergebnis ist völlig falsch.
    Kann das mal jemand nachrechnen?

    Jo, in diesem Fall lags wohl an was anderem, aber ist Dir schonmal der Gedanke gekommen, daß alle Welt die Ungenauigkeiten so fürchtet, weil eben völlig falsche Sachen dabei rauskommen können?



  • Jester schrieb:

    aber ist Dir schonmal der Gedanke gekommen, daß alle Welt die Ungenauigkeiten so fürchtet, weil eben völlig falsche Sachen dabei rauskommen können?

    Ach was, ein Taschenrechner rechnet richtig. Weiß doch jedes Kind:

    sin^2 x + cos^2 x = 0.999999999

    😉



  • Vielen Dank @ Dr. Zoidberg.
    Obwohl ich nicht verstehe wie man auf die innere Schleife kommt hab ich jetzt wenigstens die Aufgabe gelöst.



  • 0x00000001 schrieb:

    Vielen Dank @ Dr. Zoidberg.
    Obwohl ich nicht verstehe wie man auf die innere Schleife kommt hab ich jetzt wenigstens die Aufgabe gelöst.

    Eher abgetippt 🙄



  • Phillip schrieb:

    0x00000001 schrieb:

    Vielen Dank @ Dr. Zoidberg.
    Obwohl ich nicht verstehe wie man auf die innere Schleife kommt hab ich jetzt wenigstens die Aufgabe gelöst.

    Eher abgetippt 🙄

    Was meinst du mit abgetippt?
    Meinst du von hier abgetippt: http://www.informatik.uni-freiburg.de/~asalm/cos.gif ?
    Ja, zumindest teilweise.

    0x00000001 schrieb:

    Vielen Dank @ Dr. Zoidberg.
    Obwohl ich nicht verstehe wie man auf die innere Schleife kommt hab ich jetzt wenigstens die Aufgabe gelöst.

    Die äusere Schleife solte vesrtändlich sein, oder?

    public class Cosinus { 
        public static void main(String[] args) { 
            double r; 
            double x=1; 
            double cos=1; 
    
            for(int n=1; n<=10; n++) { 
                //Berechne r(n);
                cos+=r;
            } 
    
            System.out.println("Cosinus = "+cos); 
        }    
    }
    

    Das ist die äussere Schleife. Die addiert die einzelnen Elemente.
    Ich hätte vielleicht statt n ein k reinschreiben sollen, damit es besser zur Aufgabenstellung passt ist aber egal.
    cos wird am Anfang auf 1 gesetzt, weil in der Formel ( http://www.informatik.uni-freiburg.de/~asalm/cos.gif ) kommt 1 raus wenn k=0 ist. Also setze ich cos gleich auf 1 und fang dann die Berechnung mit k=1 an. (bzw. n=1)

    Die Innere Schleife

    r=1; 
    for(int k=n; k>0; k--) { 
       r*=x*x/((2*k-1)*2*k); 
    } 
    if(n%2 == 1) r*=-1;
    

    Die Berechnet ein Element der Summe.
    In der Aufgabenstellung stand zwar, dass man das rekursiv lösen sollte, ich habe das aber stattdessen in eine for Schleife gepackt.

    rekursiv sähe das ganze so aus:

    public class Cosinus {
        public static void main(String[] args) {
            double r;
            double x=1;
            double cos=0;
    
            for(int k=0; k<=10; k++) {
                r=r(2*k, x);
                System.out.println("r"+(2*k)+" = "+r);
                cos+=r;
            }
    
            System.out.println("Cosinus = "+cos);
        }
    
        static double r(int i, double x) {
            double ri;
            if(i==0) return 1;
            ri=-r(i-2, x)*x*x/((i-1)*i);
            return ri;
        }
    }
    

    Jetzt dürfte es genauso aussehen wie in der Aufgabenstellung verlangt wurde.



  • Danke für die Ausführliche Erklärung 🙂 Jetzt hab ich es verstanden. Mich haben vor allem die ganzen Indexe verwirrt, aber jetzt ist mir klar was die machen.

    Phillip schrieb:

    0x00000001 schrieb:

    Vielen Dank @ Dr. Zoidberg.
    Obwohl ich nicht verstehe wie man auf die innere Schleife kommt hab ich jetzt wenigstens die Aufgabe gelöst.

    Eher abgetippt 🙄

    Naja "abgetippt" ist noch schön formuliert, ich würde strg-c strg-v sagen 😃
    Aber immerhin hab ich es noch ein wenig optimiert, zB. k*2 <=> k<<1



  • 0x00000001 schrieb:

    Aber immerhin hab ich es noch ein wenig optimiert, zB. k*2 <=> k<<1

    Ich bezweifle aber, dass das eine Optimierung darstellt.
    Es läuft dadurch nicht schneller, wird aber unübersichtlicher.


Log in to reply