Liczby zespolone w języku C (cz.3)

Transkrypt

Liczby zespolone w języku C (cz.3)
Katedra Elektrotechniki Teoretycznej i
Informatyki
wykłady 4 - sem.III
Dr inż. M. Czyżak
Język ANSI C – wskaźniki
Wyrażenie *px ma różny sens w zależności od tego czy
występuje po lewej czy też po prawej stronie instrukcji
podstawienia.
Dla następujących definicji i instrukcji
int x=5,y, *px;
px=&x;
w instrukcji
y=*px;
wyrażenie *px reprezentuje zawartość komórki wskazywanej
przez px, czyli komórki x (jest to 5).
Natomiast w instrukcji
*px=15;
wyrażenie *px reprezentuje adres pamięci ( zmienną), pod który
można wpisać jakąś wartość.
Język ANSI C – wskaźniki
L-wartości ( ang. lvalue) i R-wartości
W języku ANSI C zmienna jest nazwanym obszarem pamięci;
L-wartość jest wyrażeniem reprezentującym pewien obszar pamięci.
Przykładem L-wartości jest identyfikator o odpowiednim typie i klasie pamięci.
Niektóre operatory jako wynik swojego zastosowania dają L-wartość,
np. jeżeli W jest wyrażeniem wskaźnikowym, to *W jest L-wartością
odnoszącą się do obiektu wskazywanego przez W. Określenie L-wartość
wywodzi się od instrukcji przypisania
W1=W2;
w której lewy argument musi L-wartością ( reprezentować pewną lokację w
pamięci).
Stosując poszczególne operatory należy zważać czy zastosowanie
danego operatora daje w wyniku L-wartość.
Język ANSI C – wskaźniki
Przykład. (L-wartość)
int x=0;
int *wski;
x=x+1;
L-wartość (lokacja pamięci)
wski = &x; /* wskaźnik wski wskazuje na x */
*wski = *wski +1;
L-wartość
Język ANSI C – wskaźniki
Arytmetyka na wskaźnikach
W językach C i C++ stosując wskaźniki można posługiwać się tzw.
ograniczoną arytmetyką na wskaźnikach. Oznacza to, że można stosować
niektóre operacje arytmetyczne, by obliczyć odpowiedni wskaźnik.
Należy jednak w każdym przypadku zważać na to, co może oznaczać wynik
danego działania. Dla wskaźników można stosować następujące operacje
wskaźnikowe:
Język ANSI C – wskaźniki
Działania arytmetyczne na wskaźnikach
Na wskaźnikach wskazujących na ten sam typ można dokonywać
następujących operacji:
- inkrementacji (++) ( zwiększania)
- dekrementacji (--)
( zmniejszania)
- dodawania do wskaźnika liczby całkowitej
- odejmowania od wskaźnika liczby całkowitej
- odejmowania wskaźników od siebie
- porównywania dwóch wskaźników.
Język ANSI C – wskaźniki
Inkrementacja wskaźnika
Jeżeli wskaźnik wsk do pewnego typu wskazuje na pewną komórkę pamięci, to
wyrażenie wsk++ wskazuje na komórkę o adresie wsk+sizeof(typ).
Przykład. Inkrementacja wskaźników do int .
int *wsk,x;
wsk
wsk=&x;
wsk++;
x
wsk++
Język ANSI C – wskaźniki
Dekrementacja wskaźnika
Jeżeli wskaźnik wsk do pewnego typu wskazuje na pewną komórkę pamięci, to
wyrażenie wsk-- wskazuje na komórkę o adresie wsk-sizeof(typ).
Przykład. Dekrementacja wskaźnika do int
int *wsk,x;
wsk--
wsk
wsk=&x;
wsk--;
x
Język ANSI C – wskaźniki
Dodawanie do wskaźnika liczby całkowitej
Jeżeli wskaźnik wsk do pewnego typu wskazuje na pewną komórkę pamięci to
wyrażenie wsk+liczba wskazuje na komórkę o adresie
wsk+liczba*sizeof(typ).
Odejmowanie od wskaźnika liczby całkowitej
Jeżeli wskaźnik wsk do pewnego typu wskazuje na pewną komórkę pamięci to
wyrażenie wsk-liczba wskazuje na komórkę o adresie
wsk-liczba*sizeof(typ).
Język ANSI C – wskaźniki
Odejmowanie wskaźników
Jeżeli dane są dwa wskaźniki wsk1 i wsk2,do tego samego typu Type, to
po wykonaniu instrukcji
diff= wsk2 - wsk1;
diff ma wartość dodatnią, jeżeli wsk2 wskazuje na wyższy adres,
i ma wartość równą liczbie elementów typu Type, które można umieścić
między adresami komórek pamięci wskazywanych przez wsk1 i wsk2.
Jeśli wsk2 wskazuje na adres niższy, diff ma wartość ujemną, a interpretacja
jest podobna.
Język ANSI C – wskaźniki
Porównywanie wskaźników
Jeśli wskaźniki wsk1 i wsk2 wskazują na ten sam typ, to
wyrażenie
wsk2>wsk1
ma wartość logiczną prawda, jeżeli wsk2 wskazuje na adres wyższy i wartość
fałsz, gdy na niższy.
Język ANSI C – wskaźniki
Przykład. L-wartości i R-wartości
#include <stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
int j=5,*wski,i=10;
wski=&i;
*wski=j;
// *wski jest L-value (L-wartoscią)
//++ * wski=j; // L-value required ( wymagana
//L-wartosc), wyrażenie nie jest
//L-wartością
* ++wski=j; // *++wski jest L-value
Język ANSI C – wskaźniki
Przykład. L-wartości i R-wartości (c.d)
//
(*wski) ++=j;
// L-value required
// wymagana L-wartość
*(wski ++)=j;
system("pause");
return 0;
}
// L-value (L-wartość)
Język ANSI C – wskaźniki
Wskaźniki i tablice
Nazwa tablicy w C jest stałym wskaźnikiem do pierwszego elementu
tablicy. Np. jeżeli stworzymy definicje
int a[5];
int *pa;
i zastosujemy instrukcję
pa=a;
to wskaźnik pa będzie wskazywał na a[0], czyli pierwszy element tablicy
a.
Stosując wskaźniki można wykonać te same operacje na tablicach, co
przy użyciu indeksowania.
Język ANSI C – wskaźniki
Przykład. Proste działania na tablicach przy użyciu wskaźników
#include <stdio.h>
int main() {
int a[5]; int *pa,i;
pa=a;
// przypisanie wskaźnikowi pa adresu elementu a[0]
*pa=10; //zapis wartości 10 do a[0]
pa++; //zwiększenie wskaźnika, wskazuje on teraz na a[1]
*pa=20; // zapis wartości 2 do a[1];
pa=pa+1; // wskaźnik wskazuje na element a[2]
for (i=2; i<5; i++){
printf("\n Podaj a[%d]=",i);
scanf("%d",pa);
pa++;
}
pa=a; // ustawienie wskaźnika na początek tablicy
// alternatywnie pa= pa-5
for (i=0;i<5;i++)
printf("\n a[%d]=%d", i,*pa++);
printf("\n");
system("PAUSE");}
Język ANSI C – wskaźniki
Przyklad. Program wczytujący tablicę dwuwymiarową przy zastosowaniu
wskaźników
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{ int tab[3][3];
int *p;
p=&tab[0][0];
int i,j;
for (i=0;i<3;i++)
for (j=0;j<3;j++)
{
printf("\n Podaj element [%d}[%d}=",i,j);
scanf("%d",p+j+i*3);
}
for (i=0;i<3;i++)
{ for (j=0;j<3;j++)
printf("
system("PAUSE");
%d",*(p+j+i*3));
printf("\n");
}
Liczby zespolone w języku C (cz.1)
Standard ISO C99 wprowadza wsparcie dla liczb zespolonych w języku
C. Jest to realizowane przez wprowadzenie słów kluczowych _Complex i
_Imaginary oraz nowych kwalifikatorów complex, _Complex_I, imaginary,
_Imaginary_I.
Mają one następujące znaczenie
- complex – identyfikator służący do tworzenia definicji typu zespolonego
- _Complex_I – identyfikator reprezentujący i −
1
- imaginary – identyfikator służący definicji typu urojonego
- _Imaginary_I – identyfikator reprezentujący− 1i typu urojonego
Nie wszystkie są obsługiwane przez przez kompilator DevC++. Obsługuje on
_Complex, _Complex_I oraz complex ( jeśli włączono plik complex.h )
Plik ten umożliwia również stosowanie identyfikatora I jako
−1
.
Liczby zespolone w języku C (cz.2)
Przykład. Zapis liczb zespolonych w programie C.
(zastosowanie I i _Complex_I)
3.0 +4.0 i
3.0+ 4.0 * I
3.0 +4.0 i
3.0+ 4.0 * _Complex_I
Liczby zespolone w języku C (cz.3)
Typy zespolone
Przykłady definicji zmiennych typów zespolonych.
float _Complex z1; // części rzeczywista i urojona są typu float
float
complex z2;
double complex
double _Complex
z3; // części rzeczywista i urojona są typu double
w[2]={ 1+2*I , -3+4*I};// definicja tablicy
//
long double _Complex
z4;
long double
z5;
complex
z inicjalizacją
Na wartościach typów zespolonych można wykonywać te same działania
arytmetyczne co na typach rzeczywistych ( +,-,*,/)
Liczby zespolone w języku C (cz.4)
W C99 wprowadzono szereg arytmetycznych funkcji standardowych
umożliwiających realizację różnego rodzaju operacji na danych zespolonych.
Poniżej podano cztery wybrane funkcje:
cabs() - oblicza wartość modułu liczby zespolonej
carg() - oblicza kąt fazowy
creal() - wyznacza część rzeczywistą liczby zespolonej
cimag() - wyznacza część urojoną liczby zespolonej
Oprócz tych funkcji istnieją specjalne konstrukcje, które umożliwiają
wczytywanie liczb zespolonych jak również wyznaczanie części rzeczywistej i
części urojonej.
Wyrażenie __ real__ zmiennaZespolona reprezentuje część rzeczywistą
zmiennej zmiennaZespolona ( __ to podwójne podkreślenie)
Wyrażenie __ imag__ zmiennaZespolona reprezentuje część rzeczywistą
zmiennej zmiennaZespolona
Poniżej w programie zastosowano wczytywanie i drukowanie wartości
zespolonych z użyciem tych konstrukcji.
Liczby zespolone w języku C (cz.5)
#include <complex.h>
#include <stdio.h>
int main(int argc, char *argv[]){
double _Complex
z1,z2;// pierwszy sposób definicji
double complex z3,z4;// drugi sposób definicji
double complex z5=100+200*I;// definicja z inicjalizacją
// Przypisywanie wartości liczbom zespolonym
z1=2+3*_Complex_I;// 2+3i
z2=4+6*I;
// 4+6i
z3=z1+z2;
// sumowanie liczb zespolonych
// podobnie odejmowanie, mnozenie i dzielenie
printf("\n z5=%f+j%f",creal(z5),cimag(z5));
// funkcja
creal(z) wyznacza część rzeczywistą liczby
Liczby zespolone w języku C (cz.6)
// wczytywanie liczby zespolonej i drukowanie
printf("\n z1=");
scanf("%lf %lf", &(__real__ z1),&(__imag__ z1));
// drukowanie liczby zespolonej (sposob 1)
printf("\n z1=%lf %lf", creal(z1),cimag(z1));
// drukowanie liczby zespolonej (sposob 2)
printf("\n z1=%lf %lf", __real__ z1,__imag__ z1);
Liczby zespolone w języku C (cz.7)
Przykład. Napisać program realizujący transformacje
gwiazda-trójkąt i trójkąt-gwiazda dla zadanych impedancji wczytywanych z
wejścia, wczytywać z klawiatury kierunek transformacji.
1
1
Z1
Z2
Z12
Z3
Z13
2
3
Z23
2
Z Z + Z 2 Z 3 + Z1 Z 2
Z12 = 1 3
Z3
Z 23 =
Z1Z 2 + Z1Z 3 + Z 2 Z 3
Z1
3
Z13 =
Z1Z 2 + Z 2 Z 3 + Z1Z 3
Z2
Liczby zespolone w języku C (cz.8)
Przykład. Napisać program obliczający prąd w obwodzie dla zadanego
napięcia wejściowego i zadanych impedancji, następnie zmodyfikować
program, tak aby dane były wprowadzane z klawiatury.
i
3
5-j3
2+j3
150ej0
8+j2.5
~
10+j6
1
5+3j
3-j2
2
Liczby zespolone w języku C (cz.9)
X ( jω )
K ( jω )
Y ( jω )
K ( jω ) =
X ( jω )
K ( jω )
- transmitacja zespolona
Y ( jω )
Liczby zespolone w języku C (cz.10)
K ( jω ) = K ( jω ) ⋅ e
K ( jω )
θ (ω )
jθ ( ω )
-charakterystyka amplitudowa
-charakterystyka fazowa
W decybelach
20 log K ( jω )
Liczby zespolone w języku C (cz.11)
Przykład.Obliczanie charakterystyki amplitudowej filtru.
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
int main ()
{ double complex z1,z2,z3;
double complex p1,p2,p3,p4,K_jOmega;
double absK_jOmega,absK_jOmega1;
double Omega=0;
int i;
p1=-0.92+0.38*I;//sprzężone bieguny transmitancji
p2=-0.92-0.38*I;
p3=-0.38+0.92*I;
p4=-0.38-0.92*I;
Liczby zespolone w języku C (cz.12)
// Obliczanie modulu charakterystyki amplitudowej
for (i=0;i<200;i++)
{
K_jOmega=(Omega*I+p1)*(Omega*I+p2)\
*(Omega*I+p3)*(Omega*I+p4);
K_jOmega=1/K_jOmega;
// obliczanie
absK_jOmega=20*log10(sqrt(creal(K_jOmega)*\
creal(K_jOmega)+cimag(K_jOmega)*cimag(K_jOmega)));
// uzycie funkcji obliczajacej modul liczby
zespolonej (drugi sposób)
absK_jOmega=20*log10(cabs(K_jOmega));
Liczby zespolone w języku C (cz.13)
// Obliczanie modulu charakterystyki amplitudowej (c.d)
printf("\n Omega=%6.2f abs_K(jOmega)=%6.2f db",\
Omega,absK_jOmega);
Omega=Omega+0.1;
getch();
}
return 0;
}

Podobne dokumenty