Fizikus C++ labor

1. hét: make és C ismétlés2. hét: pontosság és pontatlanság3. hét: azonos nevű függvények, referencia
4. hét: egyszerű osztályok5. hét: konstruktor és operator overloading6. hét: osztály dinamikus adattaggal
9. hét: >> és << használata I/O-ra, statikus tagok10. hét / 1: STL vector10. hét / 2: STL string, algorithm
11. hét: generikus algoritmusok és osztályok12. hét: öröklés13. hét: heterogén kollekció
14. hét: C++11 kitekintő15. hét: Nagyházi bemutatás

2. hét: pontosság és pontatlanság

1. feladat

Ha egész típusú változót definiálunk, akkor magától értetődő, hogy pl. 3.14-et nem tudunk eltárolni egy ilyen változóban, ezt 3-mal (vagy 4-gyel) közelíthetjük legfeljebb. Valós típusú változók esetén sem tudunk minden számot eltárolni, mert véges számú számjegy számára van hely. Egész számok esetén két ábrázolható szám között mindig 1 a különbség, valós számoknál viszont ez a különbség a konkrét eltárolt számtól függ: ha 0-hoz közeli számról van szó, akkor két ábrázolható szám között 1-nél jóval kevesebb van, 0-tól távoli számok esetén viszont 1-nél jóval nagyobb is lehet a távolság.

 

Az int i = 3; i = i + 0.99; printf("%d", i); utasításokat lefuttatva 3-at kapunk, mert az ábrázolható távolságnál kisebb értékkel próbáltuk növelni a változó értékét. Valós számoknál hasonló a helyzet. Mi az a valós szám, amelyre igaz, hogy 1-et hozzáadva nem változik az értéke? Azaz hol éri el az 1-et két ábrázolható valós szám távolsága? Segítség: while(e!=f){f=e; e+=1;} Próbáld ki float-tal! (Kipróbálhatod double-lel is, de az a labor végéig nem fog lefutni, mert nagyságrendileg 1e8 s. Egy közelítő értéket kaphatsz, ha az f=e; elé beírod, hogy e=e*1.001;)

2. feladat

A véges számú számjeggyel való tárolásnak nem csak az a következménye, hogy két ábrázolható szám között van valamekkora távolság, hanem ez is, hogy nem tárolható tetszőlegesen nagy szám. Float típusnál ez 1038 (1e38), double esetén 10308 (1e308) nagyságrendjébe esik. Nézzük ezt meg a gyakorlatban!

 

Legyen x egy float változó, amely kapjon 1e38-at értékül. Írjuk ki! Szorozzuk meg 10-zel x-et, és írjuk ki! Írjuk be, hogy x = x - x; Írjuk ki! Mit kaptunk? x==x ill. x!=x közül melyik lesz igaz? (Visual C++-ban az IND megfelel a NAN-nak)

 

Nézd meg a következő kifejezéseket is: acos(5), sqrt(–1), flt=exp(200) v. dbl=exp(2000)

3. feladat

Az (x-1)(x-10n)=0 egyenlet gyökei nyilván 1 és 10n. Bontsuk fel a zárójeleket, majd számítsuk ki az egyenlet gyökeit a megoldóképlettel n=0-tól 20-ig!

 

Tipp: a kifejtett egyenlet: x2-(1+10n)x+10n=0.

 

Az előadáson látott módon a kivonással megkapott gyököt megkaphatjuk más módon is, pontosabb eredményt kapva. Nézd meg a jegyzetedben!

4. feladat

Az ex Taylor sora sum( xn / n! ). Számítsuk ki 20 és -20 között minden egész x értékre, 50 tagot összegezzünk (n=0-tól 49-g)! Hasonlítsuk össze a beépített exp függvény eredményével! Hogyan oldható meg a probléma?

 

Tipp: a-b = 1/ab.

 

5. feladat

Számítsuk ki a sum(1/n) divergens sor első 10 millió tagjának összegét (n=1-től 10 millióig)! Az összegzést float változóban végezzük! Nézzük meg az összeget egyszer 1-től 10 millióig és egyszer 10 milliótól 1-ig! Ellenőrizzük double változóban való összegzéssel!

Gyakorló feladatok

1. Intervallumfelelzés

2. Integrál

Órai feladatok mintamegoldása

1. feladat
#include <stdio.h>

int main(){
    float e = 1, f = 0;
    while (e != f){ /*e *= 1.001; */ f = e; e += 1; }
    printf("%g\n", e);
    return 0;
}

 

2. feladat
#include <stdio.h>

int main(){
    float x = 1e38;
    printf("%g\n", x);
    x *= 10;
    printf("%g\n", x);
    x = x - x;
    printf("%g\n", x);
    return 0;
}

 

3. feladat
#include <stdio.h>
#include <math.h>

int main2(){
    float a, b, c, d, x1, x2;
    int n;

    for (n = 0, c = 1; n < 20; n++, c *= 10){
        a = 1;
        b = -(a + c);
        d = sqrt(b*b - 4*a*c);
        x1 = (-b + d) / (2 * a);
        x2 = (-b - d) / (2 * a);
        printf("n=%d, x1=%g, x2=%g\n", n, x1, x2);
    }
    return 0;
}

 

4. feladat
#include <stdio.h>
#include <math.h>

double eadiksz(double x){
    double fac = 1, xi = 1, sum = 1;
    int i;
    for (i = 1; i < 50; i++){
        xi *= x;
        fac *= i;
        sum += xi / fac;
    }
    return sum;
}

int main(){
    double i;
    for (i = 20; i > -20.5; i -= 1)
        printf("%g: %g vs. %g\n", i, eadiksz(i), exp(i));
    return 0;
}