Wzór Eulera na Pi

0

Witam mam na zadanie napisać program na wzór Eulera http://upload.wikimedia.org/wikipedia/pl/math/1/0/5/105b8dc00dfe435e95ce5d02d1df8bbb.png a nie wiem jak to w ogóle ugryźć dopiero się uczę i mnie to przerosło :(

Bardzo proszę kogoś o pomoc.

0

user image
user image
user image

Skorzystaj z tego wzoru(przyjemniejsza postac). Bardzo prosto wyliczyc pi z tego.

0

Ja by raczej spytał czy na pewno masz stosować ten wzór Eulera? Jest jeszcze wzór Eulera \frac{\Pi<sup>2}{8}=\sum\frac{1}{i</sup>2}, który łatwo zaimplementować.
Ten wzór, który podałeś wymaga zastosowania bardzo nieporęcznej rekurencji, w której trudno kontrolować precyzję obliczeń.

0

W tym wzorze co dalem(jego), ale zapisanym inaczej wystarczy napisac kod na podstawie 2-giej linijki. Tam jedynie trzeba zapamietac poprzednik do mnozenia, bo zawsze mnozymy * licznik+1/mianownik+2 i sumowac wyniki dla zadanej ilosci krokow. Na samym koncu dodac 1 i pomnozyc przez 2 i cala robota.

0

@MarekR22: Może źle rozumiem, ale przykład podany przez @Krycho (nr 2) przyrasta o coraz mniejszą liczbę per iteracja więc kontrolować dokładność można bardzo dobrze (do czasu osiągnięcia granic maszyny).

0

Chyba użyje tego i ciul. Bo wykładowca spisał właśnie tak sobie z WIKI i mi ten przydzielił a tą przerobioną przez Ciebie Krycho dostał mój kolega. Trudno się mówi lepiej mieć coś źle niż nic nie mieć :)

0

to zamiast kombinować z podmianą zadania, napisz to bez oceniania dokładności. Nie jest to trudne.
Usupełnij to:

double eulrerContinuedFractionPi(int n) {
    double an1=4; // tą wartość trzeba przyjąć w zasadzie losowo, bo nie da jej się łatwo estymować
    for (;n>0;--n) {
        an1 = 4 + (2*n+1)*(2*n+3)/an1;
    }
    ...
}
0

Witam!

Pozwolę sobie podczepić się pod temat, jako że jest on analogiczny do mojego problemu. Próbuję napisać prosty program do wyliczenia Pi wykorzystując wzór Eulera user image

Kod wygląda następująco:

 
{
  int i,n;                             
  double mianownik,suma=1, x=2.;       
  printf("Podaj n: ");
  scanf("%d", &n);                      
  for (i=1; i<=n; i++){
       mianownik=pow(x,2.);
       suma+=1/mianownik;
       x++;
       }
}

Wynik zwracany jest oczywiście błędny, stąd i moja prośba aby ktoś rzucił okiem na kod i podzielił się swoimi spostrzeżeniami. Z góry dzięki za pomoc!
Pozdrawiam

@Edit.Otrzymany przeze mnie wynik należałoby pomnożyć przez 6 a następnie wyciągnąć z tego pierwiastek?;>

0

Dokładnie. Otrzymujesz przecież (pi^2)/6. Pomnożysz i spierwiastkujesz to dostaniesz pi. Sprawdzałem.

0

Ale komplikujesz !

  unsigned n;
  double suma;
  printf("Podaj n: ");
  scanf("%u",&n);                      
  for(suma=0;n;--n) suma+=6./n/n;
  suma=sqrt(suma);
0

@_13th_Dragon, dlaczego używasz tak dużo dzieleń?

    unsigned n;
    double suma = 0.0;
    unsigned r = 1;
    unsigned skl = 0;
    printf("Podaj n: ");
    scanf("%u",&n);
    for(int i=0;i<=n;++i)
    {
        suma+=6.0/(skl+=r);
        r+=2;
    }
    suma = sqrt(suma);
0
bogdans napisał(a):

@_13th_Dragon, dlaczego używasz tak dużo dzieleń?

    unsigned n;
    double suma = 0.0;
    unsigned r = 1;
    unsigned skl = 0;
    printf("Podaj n: ");
    scanf("%u",&n);
    for(int i=0;i<=n;++i)
    {
        suma+=6.0/(skl+=r);
        r+=2;
    }
    suma = sqrt(suma);

Chociażby w celach nie zagmatwania kodu tak że nie widzisz że nie działa.
http://ideone.com/rh2fao

Nie napisałem 6./(nn) tylko dla tego że nn może wyjść poza zakres unsigned, u ciebie ski1 wyjdzie poza unsigned.

0
_13th_Dragon napisał(a):
bogdans napisał(a):

@_13th_Dragon, dlaczego używasz tak dużo dzieleń?

    unsigned n;
    double suma = 0.0;
    unsigned r = 1;
    unsigned skl = 0;
    printf("Podaj n: ");
    scanf("%u",&n);
    for(int i=0;i<=n;++i)
    {
        suma+=6.0/(skl+=r);
        r+=2;
    }
    suma = sqrt(suma);

Chociażby w celach nie zagmatwania kodu tak że nie widzisz że nie działa.
http://ideone.com/rh2fao

Nie napisałem 6./(nn) tylko dla tego że nn może wyjść poza zakres unsigned, u ciebie ski1 wyjdzie poza unsigned.

Zjadło Ci chyba pierwiastkowanie na ideone. :]

0

@_13th_Dragon
Kod zoptymalizowałem(chociaż da się na pewno zrobić to jeszcze krócej) zaraz po tym jak doprowadziłem go do poprawnego działania:

  
  int n;                              
  double pi,suma=1,x=2;       
  printf("Podaj n: ");
  scanf("%d", &n);                    
  for (;n>0; --n,x++)
      suma+=1/(pow(x,2));    
  pi = sqrt(suma*6); 

Jestem początkujący także proszę o wyrozumiałość i jeszcze raz dzięki za sugestie!

0
kiluminati napisał(a):

@_13th_Dragon
Kod zoptymalizowałem ...

Nie zoptymalizowałeś. Wręcz na odwrót.

  1. 1/pow(x,2) już lepiej dwa dzielenia 1./x/x lub np: 1/((double)x*x)
  2. Komputerowi wszystko jedno 1 dzielić na coś czy 6 dzielić na coś ten sam czas, zaś osobne mnożenie na 6 to jednak jakiś koszt.
  3. W moim kodzie zmienia się na każdym kroku jedna zmienna u ciebie dwie
    Gdzie tu optymalizacja?

Czegoś tu nie rozumiem dla maksymalnej precyzji dla double 82191236 wyliczonej przez @bogdans mamy

0

Ale to przecież nie jest maksymalna precyzja, składniki 1/(n*n) są nadal dodatnie, tylko są tak małe, że nie zmieniają sumy. Trzeba sumować od końca.

        n = 2000000000;
        suma = 0.0d;
        for(i=n;i>=1;i--)
        {
            suma+=6.0/(i*i);
        }
        System.out.printf("pi = %25.23f\n",Math.sqrt(suma)); //pi = 3,14159265311232840000000
        System.out.printf("pi = %25.23f\n",Math.PI);         //pi = 3,14159265358979300000000
        n = 82191237;
        suma = 0.0d;
        r = 1;
        skl = 0;
        for(i=0;i<=n;i++)
        {
            skl+=r;
            suma+=6.0/skl;
            r+=2;
        }
        System.out.printf("pi = %25.23f\n",Math.sqrt(suma)); //pi = 3,14159264365071700000000

1 użytkowników online, w tym zalogowanych: 0, gości: 1