[C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 00:09
od display_error
Pozdrav. Treba mi pomoć oko sledećeg zadatka u programskom jeziku C:
Napisati algoritam kojim se učitava vrednost [inlmath]\mathtt{EPS}[/inlmath] (double vrednost koja predstavlja preciznost) a zatim ispisuje prvi član niza za koga je:
[dispmath]|a_n-a_{n-1}|<\mathtt{EPS}[/dispmath]
ako se niz formira po pravilu:
[dispmath]a_n=\left(1-\frac{1}{2!}\right)\left(1+\frac{1}{3!}\right)\cdots\left(1+\frac{(-1)^n}{(n+1)!}\right)[/dispmath]
Ono što znamo je da će početna vrednost promjenjive [inlmath]n[/inlmath] biti postavljena na [inlmath]n=1[/inlmath].
Problem se pojavljuje kada se izraz [inlmath]a_n-a_{n-1}[/inlmath] sredi. Dobija se:
[dispmath]a_n-a_{n-1}=\frac{(-1)^n(n+2)}{(n+1)!}[/dispmath]
Kada bi se faktoriel nekako pokratio, bilo bi jednostavno pomoću do-while petlje proći kroz niz i pronaći član.
Ako bi morao figurisati faktoriel, onda bi se morala kreirati pomoćna funkcija.

Svaka pomoć je dobrodošla.

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 10:19
od desideri
Ja ovde ne vidim problem, ili bar ne vidim u čemu je problem.
Naime, ideja sa do-while je totalno ok, završiće ovo. Zašto ne bismo prosto rekli jednom naredbom (pseudo programski jezik, mada je skoro u svim jezicima isto):
[dispmath]\mathrm{fact}=\mathrm{fact*n}[/dispmath]
Naravno da se onda [inlmath]\mathtt{n}[/inlmath] inkrementira, a da se na početku [inlmath]\mathtt{fact}[/inlmath] inicijalizuje.
Ne znam šta će onda pomoćna funkcija.

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 14:19
od Miladin Jovic
Evo nekog mog rešenja "na brzaka". Koriguj ga malo, ako je tačno, može dosta toga tu da se popravi.

Kôd: Obeleži sve
#include<stdio.h>
#include<math.h>
main()
  {
    float x,y,eps;
    long fact=6;
    int znak,i;
    znak=-1;
    i=3;
    x=1.0/2.0;
    y=7.0/6.0;
    printf("Unesite preciznost:");
    scanf("%f",&eps);
    while(fabs(y-x)>=eps)
      {
        x=y;
        fact*=(i+1);
        y=1.0+znak*(1.0/fact);
        printf("%6f - %6f = %f\n",y,x,fabs(x-y)); /*ubaceno radi kontrole izracunavanja*/
        znak=-znak;
        i++;
      }
    printf("Trazeni broj je %6f\n",y);
  }

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 14:46
od display_error
@Miladin Jovic

Možete li objasniti inicijalizaciju promjenjivih [inlmath]\mathtt{x,z,i,fact}[/inlmath]?
Provjerio sam program, i radi kako treba, ali zar ne treba promjenjivu [inlmath]\mathtt{i}[/inlmath] incicijalizovati na [inlmath]\mathtt{1}[/inlmath]?
Takođe [inlmath]\mathtt{fact=6,x,y}[/inlmath]?

Hvala.

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 15:08
od Miladin Jovic
Onaj tvoj način koji si naveo u tvom prvom postu je neuporedivo bolje rešenje. Ja sam pročitao zadatak i počeo da ga rešavam, nisam čitao šta si pitao.
A što se tiče tvog pitanja u vezi inicijalizacije, ja sam izračunao prva dva elementa datog niza, tj. [inlmath]1-\frac{1}{2!}[/inlmath] (to je [inlmath]i=1[/inlmath]) i [inlmath]1+\frac{1}{3!}[/inlmath] (to je [inlmath]i=2[/inlmath]) pa samim tim stigli smo do [inlmath]i=3[/inlmath] i [inlmath]3!=6[/inlmath]. Ova dva prva člana sam izračunao da bih mogao da iskoristim while petlju. Nisam navikao na do while, ali ovo je tipičan primer gde se ona može primeniti.

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 16:20
od display_error
@Miladin Jovic

Ne mogu da nađem grešku kod svoje implementacije, program ništa ne ispisuje:

Kôd: Obeleži sve
#include<stdio.h>
#include<math.h>

int fact(int n)//funkcija koja racuna faktoriel od n
  {
    int i,f=1;
    for(i=1;i<=n;i++)
      f=f*i;
    return f;
  }

int main()
  {
    double as=1,an,EPS;//an je a_novo,as je a_staro
    int n=1;
    int f=fact(n+1);
    printf("EPS=");
    scanf("%lf",&EPS);
    do
      {
        n=n+1;
        an=as+((double)(pow(-1.0,n)*(n+2)))/f;
      }
    while(fabs(an-as)>EPS);
    printf("%lf",an);
    return 0;
  }


Hvala.

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 17:38
od Miladin Jovic
Nema potrebe za funkcijama. Ja ne znam optimalnije od ovoga. Ovo funkcioniše na onom postu gde si našao razliku dva uzastopna člana izražene preko [inlmath]i[/inlmath].

Kôd: Obeleži sve
#include<stdio.h>
main()
  {
    int i=1;
    float eps;
    long fakt=2;
    printf("Unesite preciznost:");zr
    scanf("%f",&eps);
    do
      {
        ++i;
        fakt*=(i+1);
      } while(((float)(i+2)/fakt)>eps);
    printf("%f\n",(i%2)? 1.0-(1.0/fakt): 1.0+(1.0/fakt));
  }

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 20:54
od Miladin Jovic
Sad videh, u uslovu do while petlje treba umesto veće napisati veće jednako.

Re: [C] Pronaći član niza prema nekom kriterijumu

PostPoslato: Četvrtak, 14. Maj 2015, 21:40
od Daniel
display_error je napisao:Dobija se:
[dispmath]a_n-a_{n-1}=\frac{(-1)^n(n+2)}{(n+1)!}[/dispmath]

:techie-error: Ne dobija se to. Ti si verovatno radio kao da je [inlmath]a_n=1+\frac{\left(-1\right)^n}{\left(n+1\right)!}[/inlmath], a zapravo je [inlmath]a_n=\left(1-\frac{1}{2!}\right)\left(1+\frac{1}{3!}\right)\cdots\left(1+\frac{\left(-1\right)^n}{\left(n+1\right)!}\right)[/inlmath].

Izrazimo [inlmath]a_n[/inlmath] preko [inlmath]a_{n-1}[/inlmath]:
[dispmath]a_n=\underbrace{\left(1-\frac{1}{2!}\right)\left(1+\frac{1}{3!}\right)\cdots\left(1+\frac{\left(-1\right)^{n-1}}{n!}\right)}_{a_{n-1}}\left(1+\frac{\left(-1\right)^n}{\left(n+1\right)!}\right)\\
\Rightarrow\quad a_n=\left(1+\frac{\left(-1\right)^n}{\left(n+1\right)!}\right)a_{n-1}[/dispmath]
Odatle je [inlmath]a_n-a_{n-1}[/inlmath] jednako
[dispmath]a_n-a_{n-1}=\left(1+\frac{\left(-1\right)^n}{\left(n+1\right)!}\right)a_{n-1}-a_{n-1}=\left[\left(\cancel1+\frac{\left(-1\right)^n}{\left(n+1\right)!}\right)-\cancel1\right]a_{n-1}=\frac{\left(-1\right)^n}{\left(n+1\right)!}a_{n-1}[/dispmath]
Odatle sledi da prva prethodna razlika susednih članova, [inlmath]a_{n-1}-a_{n-2}[/inlmath], iznosi
[dispmath]a_{n-1}-a_{n-2}=\frac{\left(-1\right)^{n-1}}{n!}a_{n-2}=\frac{\left(-1\right)^{n-1}}{n!}\cdot\frac{1}{1+\frac{\left(-1\right)^{n-1}}{n!}}\cdot\underbrace{\left(1+\frac{\left(-1\right)^{n-1}}{n!}\right)a_{n-2}}_{a_{n-1}}=[/dispmath][dispmath]=-\frac{\left(-1\right)^n}{\left(n+1\right)n!}\cdot\frac{n+1}{1+\frac{\left(-1\right)^{n-1}}{n!}}a_{n-1}=-\frac{n+1}{1+\frac{\left(-1\right)^{n-1}}{n!}}\cdot\underbrace{\frac{\left(-1\right)^n}{\left(n+1\right)!}a_{n-1}}_{a_n-a_{n-1}}=-\frac{n+1}{1+\frac{\left(-1\right)^{n-1}}{n!}}\left(a_n-a_{n-1}\right)[/dispmath][dispmath]\Rightarrow\quad\enclose{box}{a_n-a_{n-1}=-\frac{1+\frac{\left(-1\right)^{n-1}}{n!}}{n+1}\left(a_{n-1}-a_{n-2}\right)}[/dispmath]
Ovime smo dobili rekurentnu formulu za razliku susednih članova, koja je pogodna za optimalan algoritam, kojim bi se postigla maksimalna brzina izvršavanja programa.
Vrednost početne razlike, [inlmath]a_2-a_1[/inlmath], lako odrediš, njena vrednost je [inlmath]\frac{1}{12}[/inlmath]. Sledeću razliku, [inlmath]a_3-a_2[/inlmath], računaš tako što u gornju rekurentnu formulu uvrstiš [inlmath]n=3[/inlmath] i tako za svaku narednu razliku. Naravno, poželjno je, što i prethodnici rekoše, da kreiraš neku promenljivu za faktorijel koju ćeš pri svakom prolasku kroz petlju množiti novom vrednošću [inlmath]n[/inlmath], kako ne bi pri svakom prolasku kroz petlju faktorijel računao od početka, tj. od jedinice.