C, Obliczenie funkcji + przesunięcie bitowe.

0

Witam

Mam problem z zadaniem:
b2.png

Rozwiązałem podpunkt a), ale nie rozumiem co trzeba zrobić z podpunktem b). Proszę o jakieś wytłumaczenie.

Podpunkt A):

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

double fun (int t, double gamma);
int silnia(int a);
main()
{
printf("%lf\n",fun(2,0.7));
system("pause");      
}
int silnia(int a)
{ int odp;
    if(a>0)
    {
           odp=a*silnia(a-1);
           }
    else { 
         odp=1;
         }
return odp;
}
    
    
double fun (int t, double gamma)
{
       int j=0,pot;
       double s=1,cz;
       
       
       do{
              j=j+1;
              pot=2*j;
              cz=(1*pow(t,pot)/(silnia(pot)));
              s=s+cz;
              }
       while(cz<gamma);
return s;
}
1

w matematyce m>>1 nie oznacza przesunięcia bitowego, tylko że m jest DUŻO DUŻO większe od 1 (np 1000000000)
http://pl.wikipedia.org/wiki/Lista_symboli_matematycznych

0

Dzięki, główna niewiadoma rozwiązana, ale mam jeszcze wątpliwości:

  1. Dajmy na to że m=20;
    Piszę algorytm który obliczą średnią z 3 pierwszych liczb czyli od m=1 do m=3, wypisuje to, potem od m=2 do m=4 i wypisuje itd. aż do m=20?

  2. Mają być losowe wartości od -4 do 6, a linijkę niżej pisze żeby korzystać z funkcji rand(0,1) - od 0 do 1?

@adf88
Na zajęciach robiliśmy kiedyś program który też był z dokładnością i chodziło tam o dokładność własnie ostatniego wyrazu czyli program ma robić funkcje aż ostatni wyraz będzie mniejszy od np. 0,0001.

0

W matematyce "m >> 1" oznacza "m dużo większe niż 1".

Pierwszą część zadania masz źle zrobioną. Ostatni wyraz szeregu jaki obliczyłeś nie jest dokładnością!
Obliczając sumę pierwszych n wyrazów dostajesz:
user image
To co nie zostało obliczone czyli reszta to
user image
Musisz liczyć dopóki nie będziesz miał pewności, że reszta jest nie większa niż ρ. Jak to określić? Musisz ograniczyć ten szereg od dołu jakąś prostszą funkcją którą będzie się dało obliczyć "od razu". Matematyka się kłania.

//EDIT
No i oczywiście user imagewięc możesz pominąć ten wyraz. Również nie obliczaj silni za każdym razem na nowo. W kolejnych krokach przemnażaj poprzednio obliczoną raz przez 2j.

//EDIT2
Musisz jeszcze określić, czy szereg jest malejący. W przeciwnym razie twój program się zawiesi, jeśli jest niemalejący.

0

Na zajęciach robiliśmy kiedyś program który też był z dokładnością i chodziło tam o dokładność własnie ostatniego wyrazu czyli program ma robić funkcje aż ostatni wyraz będzie mniejszy od np. 0,0001.
Poprawiłem na

while(cz>gamma);

Dalej mam problem z typ podpunktem B, jakby ktoś umiał wytłumaczyć co ten algorytm ma robić po kolei.

1

Faktycznie jest to trochę mało sensownie napisane, ale z tego co ja zrozumiałem masz m razy wylosować t i dla każdego takiego t obliczyć średnią pierwszych trzech wyrazów ciągu (w sumie nie jest napisane czy to mają być pierwsze trzy czy dowolne inne trzy wyrazy, byle kolejne, może jakiś diabeł tam się kryje...).
//EDIT
W sumie chyba wiem o co chodziło pytającemu (ach, jak ja lubię rozszyfrowywać pytania...). Prawdopodobnie masz wylosować t, obliczyć średnią z pierwszych trzech wyrazów ciągu, wylosować kolejne t, obliczyć średnią z kolejnych trzech wyrazów ciągu (ale już z nowym t), wylosować kolejne t ... i tak m razy. Pewności nie mam.

0

Dodam że w drugiej grupie jest polecenie "Podaj algorytm, który obliczy trzy kolejne maksymalne wartości f(t)..."

Niezrozumiałe polecenie, a jutro mam poprawke...

0

Zgadzam się z adf88 - wg mnie zadanie jest celowo niezbyt poprawnie sformułowane:
a) wstęp to równoważnik zdania a nie zdanie - powinno być jak rozumiem "Dana jest zależność wartości f(t), m - liczba całkowita i gamma - liczba rzeczywista"
b) szereg nieskończony niepotrzebnie jest podany jako nieskończony skoro mamy obliczyć jego 3 kolejne elementy
c) z drugiej strony mamy liczyć do osiągnięcia określonej dokładności

Wg mnie w zadaniu jest wewnętrzna sprzeczność m. (b) i (c).

0

Albo jeszcze inaczej?

Podaj algorytm, który obliczać będzie średnie z trzech kolejnych wartości f(t).
Może wcale nie chodzi o 3 kolejne wyrazy szeregu. Może trzeba obliczyć f(t) z zadaną dokładnością dla trzech różnych t i wyciągnąć średnią? K*** sam już nie wiem, obstawał bym przy tym ostatnim.

wahuu napisał(a):
  1. Mają być losowe wartości od -4 do 6, a linijkę niżej pisze żeby korzystać z funkcji rand(0,1) - od 0 do 1?
    Pomnóż wynik rand'a (0..1) przez 10 (wyjdzie 0..10) i odejmij 4 (wyjdzie -4..6).
0

te m to dziwna sprawa, wiadomo, że m jest całkowite i dużo większe od 1, ale we wzorze go nie widać i nie widzę by miało jakikolwiek wpływ na wynik obliczeń.
Nic tyko zignorować m i wtedy zadanie jest jasne: obliczyć f(t) dla trzech wartości t z zdaną dokładnością.
Na dodatek te (-1)^(2j) to już totalny bezsens (zawsze równe 1). Coś mi się wydaje, że zadanie ma za dużo literówek zmieniające sens zadania.

0

Wykombinowałem takie coś:
Podaje m liczb które ma wylosować z przedziału <-4,6> - to są "t".
Potem liczy funkcje f(t) dla pierwszych 3 wyrazów i sprawdza jaka jest ich średnia.
Pewnie nie o to chodzi bo w drugiej grupie ma obliczyć jakieś elementy maksymalne, a inne zadania są bardzo podobne między grupami typu inne potęgi itp.

Listing:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void wtfb (int m);
int silnia(int a);
main()
{
      
wtfb(8);
system("pause");      
}
int silnia(int a)
{ int odp;
    if(a>0)
    {
           odp=a*silnia(a-1);
           }
    else { 
         odp=1;
         }
return odp;
}
void wtfb (int m)
{
     double sr;
     int i,t;
     
                       for (i=0;i<m;i++)
                       {   
                           t=rand()%11-4;
                           int j=0,pot;
                           double s=1,cz;
       
       
                                  while(j<3){
                                  j=j+1;
                                  pot=2*j;
                                    cz=(1*pow(t,pot)/(silnia(pot)));
                                                s=s+cz;
                                    }
                                    
                                    printf("srednia f(%d)=%lf\n",t,s/3);
                         }     
return 0;
}        

Pisane na szybkiego więc coś może się nie zgadzać.

Przyklad przy m=20:
przykl.png

0

rand()%11-4;
W ten sposób wylosujesz jedynie liczby całkowite. Dla liczb rzeczywistych (sugeruje to zapis rand()∈(0,1)) Powinno być:
10.0 * rand() / RAND_MAX - 4

No i ogólnie kiepsko to napisane. W zasadzie kompletne minimum. Przede wszystkim można ulepszyć obliczanie silni. Nie licz iloczynu od nowa za każdym razem, skorzystaj z tego, co obliczyłeś do tej pory. Wtedy zamiast n*n mnożeń wykonasz tylko n mnożeń.

Zamiast

for(j = 0; ; j++) {
   double silnia = oblicz_silnie(2 * j);
   /* ... */
}

wystarczy

double silnia = 1;
for(j = 0; ; j++) {
   /* ... */
   silnia *= (2 * j + 1) * (2 * j + 2);
}
1
png.latex?%5Csum_%7Bj%3D0%7D%5E%7B%5Cinfty%7D%20(-1)%5E%7B2j%7D%5Cfrac%7Bt%5E%7B2j%7D%7D%7B(2j)!%7D%20%3D%20%5Csum_%7Bj%3D0%7D%5E%7B%5Cinfty%7D%20%5Cfrac%7Bt%5E%7B2j%7D%7D%7B(2j)!%7D%20%3D%20%5Csum_%7Bk%3D0%2C2%2C4%2C6%2C...%7D%5E%7B%5Cinfty%7D%20%5Cfrac%7Bt%5Ek%7D%7Bk!%7D%20%5C%5C%20%5Ctextup%7BTeraz%20znajdujemy%20zale%C5%BCno%C5%9B%C4%87%20mi%C4%99dzy%20kolejnymi%20wyrazami%20aby%20przyspieszy%C4%87%20obliczenia%7D%5C%5C%20a_k%20%3D%20%5Cfrac%7Bt%5Ek%7D%7Bk!%7D%20%5C%5C%20a_%7Bk%2B2%7D%20%3D%20%5Cfrac%7Bt%5E%7Bk%2B2%7D%7D%7B(k%2B2)!%7D%20%3D%20%5Cfrac%7Bt%5Ek%7D%7Bk!%7D%5Ccdot%5Cfrac%7Bt%5E2%7D%7B(k%2B1)(k%2B2)%7D%20%3D%20a_k%5Ccdot%5Cfrac%7Bt%5E2%7D%7B(k%2B1)(k%2B2)%7D

EDIT: A tak naprawdę, ta suma to rozwinięcie funkcji cosh(t)
png.latex?f(t)%20%3D%20%5Csum_%7Bk%3D0%2C2%2C4%2C6%2C...%7D%5E%7B%5Cinfty%7D%20%5Cfrac%7Bt%5Ek%7D%7Bk!%7D%20%3D%20%5Csum_%7Bk%3D0%7D%5E%7B%5Cinfty%7D%20%5Cfrac%7B1%5Ek%2B(-1)%5Ek%7D%7B2%7D%5Ccdot%20%5Cfrac%7Bt%5Ek%7D%7Bk!%7D%20%3D%20%5Cfrac12%20%5Csum_%7Bk%3D0%7D%5E%7B%5Cinfty%7D%20%5Cleft%20(%20%5Cfrac%7Bt%5Ek%7D%7Bk!%7D%2B%5Cfrac%7B(-t)%5Ek%7D%7Bk!%7D%20%5Cright%20)%20%3D%20%5Cfrac12%20%5Cleft%20(%20e%5Et%20%2B%20e%5E%7B-t%7D%20%5Cright%20)%20%3D%20%5Ccosh(t).

#include <cstdio>
#include <cmath>
#include <cassert>


double f(double t, double delta) {
    assert(delta > 0);
    const double t2 = t*t;
    double ak = 1.0;        // ak > 0 dla kazdego k parzystego
    double sum = ak;

    for (int k = 0; ak > delta; k += 2) {
        ak *= t2/((k+1)*(k+2));
        sum += ak;
    }

    return sum;
}

bool isCorrect(double t, double delta) {
    return delta < 0  ||  fabs(cosh(t) - f(t,delta)) < delta;
}

void testCorrectness() {
    unsigned long passed = 0;
    unsigned long failed = 0;

    for (double t = -10.0; t < 10.0; t += 0.01)
        for (double delta = 0.000000001; delta < 1; delta *= 10)
            if (isCorrect(t,delta)) {
                passed++;
            } else {
                failed++;
                printf("FAIL: for t == %g, delta == %g\n"
                       "  expected %g, but was %g\n",
                       t, delta, cosh(t), f(t,delta));
            }

    printf("Ran %lu tests.\n", passed+failed);
    if (failed == 0)
        puts("OK.");
    else
        printf("%lu of them failed! (%lu passed).\n", failed, passed);
}

int main() {
    testCorrectness();
}
0

Wielkie dzięki za pomoc, egzamin napisany, wydaje mi się że zdam ;)
Pozdrawiam

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