Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
Facu
lty o
f In
form
ati
on
Tech
no
log
y
NGÔN NGỮ LẬP TRÌNH C/C++
TS. Nguyễn Chí Trung
Khoa Công nghệ thông tin
Đại học Sư Phạm Hà Nội
2.1.Các toán tử chọn lựa if và switch
2.2.Toán tử lặp for
2.2.Toán tử lặp while
2.3. Một số bài toán tính toán gần đúng
Chương 2. Các toán tử điều khiển trong
C/C++
• Cú pháp
– Dạng khuyết:
if(biểu_thức) { nhóm_lệnh; }
– Dạng đủ:
if(biểu_thức) { nhóm_lệnh_1; }
else {nhóm_lệnh_2;}
• Ngữ nghĩa
• Chú ý:
– biểu thức có giá trị 1 (TRUE) hoặc 0 (FALSE)
– Nếu nhóm lệnh chỉ có 1 câu lệnh thì không cần khối lệnh {…}
Toán tử rẽ nhánh if
NCT.FIT.HNUE 4
• Ví dụ 1: Giải phương trình bậc hai: ax2 + bx + c (a 0)
#include <iostream>
#include <conio.h>
#include <math.h>
#include <iomanip>
using namespace std;
int main()
{ float a,b,c,d,x1,x2;
cout<<"\n nhap a,b,c: "; cin >> a >> b >>c;
cout<<setiosflags(ios::showpoint)<<setprecision(3);
d=b*b-4*a*c;
if (d<0) cout<< "\n phuong trinh vo nghiem";
else if (d==0) cout<<"\n phuong trinh co nghiem kep " << -b/(2*a);
else { x1=(b+sqrt(d))/(2*a); x2=(bsqrt(d))/(2*a);
cout << "\n phuong trinh co 2 nghiem phan biet: ";
cout << "\nx1 = " << x1 << "\nx2 = " << x2; }
return 0; }
Toán tử rẽ nhánh if
NCT.FIT.HNUE 5
• Ví dụ 2: Nhập từ bàn phím điểm trung bình môn của một sinh viên, in lên
màn hình xếp loại học lực sinh viên đó: Yếu (dtb<5.0); TB (5.0 ≤ dtb < 6.5);
Khá (6.5 ≤ dtb <8.0); Giỏi (dtb ≥8.0).
#include <iostream.h>
#include <conio.h>
void main()
{ float dtb;
char *xl;
cout << "\n nhap diem trung binh: "; cin >> dtb;
if (dtb<5.0) xl="YEU";
else if (dtb<6.5) xl="TRUNG BINH";
else if (dtb<8.0) xl="KHA";
else xl="GIOI";
cout << "\n xep loai sinh vien do la “ << xl;
getch(); }
Toán tử rẽ nhánh if
NCT.FIT.HNUE 6
• Cú pháp
switch(biểu_thức_nguyên){
case 1:
nhóm_lệnh_1;
case 2:
nhóm_lệnh_2;
...
case n:
nhóm_lệnh_n;
[default : nhóm_lệnh_mặc_định; ]
}
• Ngữ nghĩa: Khi biểu thức có giá trị k (k≤n) thì bắt đầu từ lệnh có nhãn k
được thực hiện. Các lệnh có nhãn bên dưới vẫn tiếp tục được thực hiện nếu
như trước đó không có lệnh ngắt break.
Toán tử chuyển switch
NCT.FIT.HNUE 7
• Ví dụ 1: Tìm hiểu toán tử switch
#include <iostream.h>
void main()
{
int i;
cout << "\n i= "; sin >> i;
switch (i) {
case 1 : cout << "\n lenh 1";
case 2 : cout << "\n lenh 2";
case 3 : cout << "\n lenh 3";
case 4 : cout << "\n lenh 4";
default : cout << "\n lenh default";
}
getch();
}
Toán tử chuyển switch
NCT.FIT.HNUE 8
Nếu ta nhập i=1 thì kết quả là
lenh 1
lenh 2
lenh 3
lenh 4
lenh default
Nếu ta nhập i=3 thì kết quả là
lenh 3
lenh 4
lenh default
Từ đó biến i chỉ có tác dụng
quyết định bắt đầu từ lệnh nào
được thực hiện.
• Ví dụ 2: Cho biết kết quả in ra màn hình trong chương trình sau
nếu ban đầu ta nhập i bằng 1.
#include <iostream.h>
#include <conio.h>
void main()
{ int i;
cout << "\n i= "; cin >> i;
switch (i) {
case 1 : cout << "\n" << i; i+=4;
case 3 : cout << "\n" << i; i+=2;
case 5 : cout << "\n" << i; i+=9;
case 14 : cout << "\n" << i; i+=2;
default : cout << "\n" << i; i=100;
}
cout << "\n" << i; getch(); }
Toán tử chuyển switch
NCT.FIT.HNUE 9
• Ví dụ 3: Ứng dụng của lệnh break trong toán tử switch
Một tháng có 26 ngày công.
Một công nhân có thể làm thêm từ 1 đến 4 ngày.
Số tiền thưởng theo số ngày làm thêm được quy định như sau:
Nếu số ngày làm thêm là:
– 1 thì thưởng 100.000 đ
– 2 thì thưởng 250.000 đ
– 3 thì thưởng 400.000 đ
– 4 thì thưởng 550.000 đ
Lương gốc của một công nhân là 4.500.000 đồng.
Hãy viết chương trình tính tổng lương của một công nhân khi biết
số ngày làm thêm của họ.
Toán tử chuyển switch
NCT.FIT.HNUE 10
• Ví dụ 3: Ứng dụng của lệnh break trong toán tử switch
#include <iostream.h>
#include <conio.h>
void main()
{ int sn,thuong;
cout "\n so ngay lam them = "; cin >> sn;
switch (sn) {
case 1 : thuong=100; break;
case 2 : thuong=250; break;
case 3 : thuong=400; break;
case 4 : thuong=550; break;
default : thuong=0;
}
cout << "\n Tong luong la " << 1000*((long)thuong+1500));
getch(); }
Toán tử chuyển switch
NCT.FIT.HNUE 11
• Ví dụ 4: Ứng dụng của toán tử switch
– Chẳng hạn nếu ta nhấn nút A thì từ trạng thái (10011) sẽ biến
thành trạng thái (00111); nhấn tiếp nút B, sẽ biến thành trạng
thái 01110),...
– Gọi (k1, k2, k3, k4, k5) là trạng thái xuất phát của máy, hãy
xác định trạng thái mới của máy sau khi nhấn một nút nào đó.
Toán tử chuyển switch
NCT.FIT.HNUE 12
• Cú pháp
Toán tử lặp for
NCT.FIT.HNUE 14
• Hoạt động của toán tử (lặp) for:
Bước 1: Tính giá trị biểu thức 1;
Bước 2: Nếu biểu thức 2 sai thì thực hiện Bước 5 (kết thúc)
Bước 3: /* ngầm hiểu biểu thức 2 đúng */
– Thực hiện Nhóm_lệnh.
– Tính giá trị biểu thức 3.
Bước 4: Quay về Bước 2.
Bước 5: Kết thúc.
for (biểu_thức1; biểu_thức2; biểu_thức3) {nhóm_lệnh;}
• Ví dụ: Đảo ngược dãy số thực trong mảng x
float x[] = {6.3, -4.5, 7.2, 8.4 , -2.1}
int n = sizeof(x)/sizeof(float);
void main() {
int i,j; float c;
for(i=0,j=n-1 ; i<j ; i++, j) { c=x[i]; x[i] =x[j]; x[j]=c;}
cout<<“\day so sau khi dao la:”;
for(i=0; i<n ; i++) cout<<x[i]<<“\t”; cout<<endl;
getch();
}
Chú ý: Một biểu thức có thể bao gồm một số biểu thức ngăn cách
nhau bởi dấu phẩy
Toán tử lặp for
NCT.FIT.HNUE 15
• Tính linh hoạt của toán tử for
Các biểu thức 1, 2, 3 trong for có thể vắng mặt.
Nếu biểu thức 1 vắng mặt (tại đó có 1 dấu chấm phẩy) thì những
lệnh khởi đầu thường được viết trước trước for.
Nếu biểu thức 2 vắng mặt (tại đó có 2 dấu chấm phẩy) thì ngầm
định luôn đúng; for kết thúc bởi các lệnh break/goto/ return.
Nếu biểu thức 3 vắng mặt (tại đó có 1 dấu chấm phẩy) thì nó
thường được viết gộp chung với nhóm_lệnh (thân vòng lặp for).
Thân vòng lặp for cũng có thể vắng mặt tại đó là dấu chấm phẩy.
Trong thân vòng lặp for {...} nếu gặp lệnh continue thì các lệnh
còn lại được bỏ qua và chuyển đến xét biểu thức 3.
Toán tử lặp for
NCT.FIT.HNUE 16
• Các câu lệnh sau đây là tương đương:
Cách 1 Đủ các thành phần và thân for
for(i=0,j=n1; i<j ; i++, j ) { c=x[i]; x[i] =x[j]; x[j]=c;}
Cách 2 Khuyết biểu thức 1
i=0; j=n 1;
for( ; i<j ; i++,j ) {c=x[i]; x[i] =x[j]; x[j]=c;}
Cách 3 Khuyết biểu thức 2
for(i=0, j=n1 ; ; i++, j) {c=x[i]; x[i] =x[j]; x[j]=c; if (i>j)
break;}
Cách 4 Khuyết biểu thức 3
for(i=0, j=n1; i<j ;) {c=x[i]; x[i] =x[j]; x[j]=c; i++; j;}
Cách 5 Khuyết thân for:
for(i=0,j=n1 ; i<j ; c=x[i], x[i] =x[j], x[j]=c, i++, j);
Toán tử lặp for
NCT.FIT.HNUE 17
• Các cách tương đương khác:
Cách 6 Khuyết cả 3 biểu thức
i=0; j=n-1;
for(;;) {c=x[i]; x[i] =x[j]; x[j]=c; if(i++> j) break;}
Cách 7 Khuyết biểu thức 1 và biểu thức 3
i=0; j=n-1;
for(;i<j;){c=x[i]; x[i] =x[j]; x[j]=c; i++; j;}
Cách 8 Khuyết biểu thức 2 và biểu thức 3
for(i=0, j=n-1;;) {c=x[i]; x[i]=x[j]; x[j]=c; if(i++>j) goto next;}
next: cout<<”done!”;
Và các cách khác ...
Toán tử lặp for
NCT.FIT.HNUE 18
• Ví dụ 1: Tính an với a>0, n>0
#include <stdio.h> //Chuong trinh nay dung stdio cua C
void main() {
int a,n,i;
long t=1;
printf("\n nhap a,n : "); scanf("%d%d",&a,&n);
for(i=1;i<=n;t*=a,i++);
printf("\n %d^%d = %ld",a,n,t);
getch();
}
Toán tử lặp for
NCT.FIT.HNUE 19
• Ví dụ 2: Tính an với a≠0, n≠0
#include <stdio.h> //Chuong trinh nay dung stdio cua C
void main() {
int a,n,b,m,i;
float t=1;
printf("\n nhap a,n : "); scanf("%d%d",&a,&n);
b=abs(a); m=abs(n);
for(i=1;i<=m;t*=b,i++);
if(n<0) t=1/t;
if(a<0 && (n%2!=0)) t=-t;
printf("\n %d^%d = %0.2f",a,n,t);
getch(); }
Toán tử lặp for
NCT.FIT.HNUE 20
• Ví dụ 2: Tính an với a≠0, n≠0
#include <iostream> //Chuong trinh nay dung iostream cuar C++
using namespace std;
int main() {
int a,n,b,m,i;
float t=1;
cout<<"\n nhap a,n : "; cin>>a>>n;
b=abs(a); m=abs(n);
for(i=1;i<=m;t*=b,i++);
if(n<0) t=1/t;
if(a<0 && (n%2!=0)) t=-t;
cout<<a<<“^”<<n<<“=”<<t);
getch(); return 0;}
Toán tử lặp for
NCT.FIT.HNUE 21
• Cú pháp
– Dạng 1
while(biểu_thức) { nhóm_lệnh;}
– Dạng 2
do { nhóm_lệnh } while (biểu_thức);
• So sánh
– Giống nhau: nhóm lệnh lặp còn thực hiện khi biểu thức còn
đúng (biểu_thức == 1)
– Khác nhau: Dạng 1 kiểm tra điều kiện trước còn dạng 2 kiểm
tra điều kiện sau. Vì vậy, do-while cho phép nhóm lệnh lặp
thực hiện ít nhất một lần.
Toán tử lặp while
NCT.FIT.HNUE 23
• Ví dụ 1: Viết đoạn chương trình nhập số nguyên n > 0.
– Dùng do-while
do {cout<<“\n nhap n: ”; cin>>n;
} while(n<=0);
– Dùng while
cout<<“\n nhap n: ”; cin>>n;
while(n<=0) { cout<<“\n nhap n:”; cin>>n;}
hoặc
while(1)
{ cout<<“\n nhap n: ”; cin>>n; if(n>0) break;}
Toán tử lặp while
NCT.FIT.HNUE 24
• Ví dụ 2: Tìm UCLN của 2 số nguyên dương a,b nhập từ bàn phím.
Phương pháp trừ liên tiếp
#include <iostream.h>
#include <conio.h>
void main()
{ int a,b,a1,b1;
cout<<"\n nhap 2 so a,b :"; cin>>a>>b;
a1=a; b1=b;
while(a!=b) if(a>b) a-=b; else b-=a;
cout<<"uscln(“<<a1<<”,”<<b1<<”)=”<<b;
getch(); }
Toán tử lặp while
NCT.FIT.HNUE 25
• Ví dụ 3: Tìm UCLN của 2 số nguyên dương a,b nhập từ bàn phím.
Phương pháp chia liên tiếp
#include <iostream.h>
#include <conio.h>
void main()
{ int a,b,a1,b1,r;
cout<<"\n nhap 2 so a,b :"; cin>>a>>b;
a1=a;b1=b;
while((r=a%b)!=0) {a=b;b=r;}
cout<<"uscln("<<a1<<", "<<b1<<")="<<b;
getch();
}
Toán tử lặp while
NCT.FIT.HNUE 26
<Biểu thức 1> Phép SS <Biểu thức 2>
Ví dụ:
if (r = a%b == p=m/n) {...}
• Khoảng phân li nghiệm
Cho hàm số f(x) xác định và liên tục trong miền D R. Nếu
phương trình f(x)=0 có duy nhất một nghiệm x* (a, b) thì
khoảng (a, b) được gọi là khoảng phân ly nghiệm x*.
• Định lí: Nếu hàm số f(x) liên tục và đơn điệu trong khoảng [a, b]
và f(a).f(b) < 0 thì (a, b) là khoảng phân ly của một nghiệm của
phương trình f(x) = 0.
• Cách tìm khoảng phân li nghiệm
Phương pháp giải tích : Khảo sát sự biến thiên hàm số
Phương pháp đồ thị: Xác định các khoảng chứa các điểm cắt
Giải gần đúng phương trình phi tuyến
NCT.FIT.HNUE 28
• Input: (a, b) là khoảng phân li của một nghiệm của phương trình
f(x)=0; là sai số
• Output: Nghiệm gần đúng với sai số
• Thuật toán
Bước 1: Tính x0=(a+b)/2;
Bước 2: Xử lí một trong 3 khả năng sau đây:
(i) Nếu f(x0) = 0 thì đưa ra x0 là nghiệm và kết thúc thuật toán;
(ii) Nếu f(a)f(x0) < 0 thì gán b = x0;
(iii) Nếu f(x0)f(b) < 0 thì gán a = x0;
Bước 3: Nếu |a-b| > thì quay về bước 1;
Bước 4: Đưa ra nghiệm x0.
Giải phương trình bằng phương pháp chia đôi
NCT.FIT.HNUE 29
• Ví dụ về phương pháp chia đôi
• Tìm nghiệm dương của phương trình 4ex-2x2 = 0 với độ chính
xác = 10-3
Giải phương trình bằng phương pháp chia đôi
NCT.FIT.HNUE 30
a b x0 f(a) f(b) f(x0) |b-a|<0.01
1 0 1 0.5 3 -0.71828 1.851279 FALSE
2 0.5 1 0.75 1.851279 -0.71828 0.758 FALSE
3 0.75 1 0.875 0.758 -0.71828 0.069875 FALSE
4 0.875 1 0.9375 0.069875 -0.71828 -0.3114 FALSE
5 0.875 0.9375 0.90625 0.069875 -0.3114 -0.1176 FALSE
6 0.875 0.90625 0.890625 0.069875 -0.1176 -0.02308 FALSE
7 0.875 0.890625 0.882813 0.069875 -0.02308 0.023594 FALSE
8 0.882813 0.890625 0.886719 0.023594 -0.02308 0.000307 TRUE
9 0.886719 0.890625 0.888672 0.000307 -0.02308 -0.01137 TRUE
10 0.886719 0.888672 0.887695 0.000307 -0.01137 -0.00553 TRUE
• Chương trình
Giải phương trình bằng phương pháp chia đôi
NCT.FIT.HNUE 31
#include <iostream.h>
#include <math.h>
#include <iomanip.h>
float f(float x)
{return (4-exp(x)-2*x*x);}
void main(){
cout<<setiosflags(ios::
showpoint)<<setprecision(5);
float a, b, x0, epsilon;
a=0; b=1; epsilon=0.01;
while (fabs(a-b)>=epsilon)
{ x0=(a+b)/2;
if(f(a)*f(x0)<0) b=x0;
else
if(f(x0)*f(b)<0) a=x0;}
cout<<"x0="<<x0<<endl;
}
Điểm x0 thỏa mãn f(x0)f”(x0) > 0 gọi là điểm Fourier
Giải phương trình bằng phương pháp tiếp tuyến
NCT.FIT.HNUE 32
x*
f(x0)
x0 x1
f(x1)
x2
y = f’(x0)(x – x0) + f(x0)
)('
)(
0
001
xf
xfxx
)('
)(
11
1112
xf
xfxx
)('
)(
1
11
n
nnn
xf
xfxx
...
• Input: f(x)=0 xn = xn-1 + f(xn-1)/f’(xn-1)
g(x), sai số , điểm fourier x0
• Output: Nghiệm gần đúng của f(x)=0 với sai số
• Thuật toán
Bước 1: Khởi tạo sai số e = 1
Bước 2: Lặp quá trình sau đây khi e >
2.1. Tính x = g(x0)
2.2. Tính e = abs(x-x0);
2.3. Gán x0 = x;
Giải phương trình bằng phương pháp tiếp tuyến
NCT.FIT.HNUE 33
• Ví dụ về phương pháp tiếp tuyến
• Tìm nghiệm dương của phương trình x2x1=0 với độ chính xác
là 0.001.
• Xác định điểm Fourier và hàm lặp xn=g(xn-1):
Điểm Fourier: x0=2; Hàm lặp
Giải phương trình bằng phương pháp tiếp tuyến
NCT.FIT.HNUE 34
12
1
1
2
1
n
nn
x
xx
n xn xn- xn-1 (xn- xn-1)2
1 1.666666 -0.333333 0.111111
2 1.619048 -0.047619 0.002267
3 1.618034 -0.001013 0.000001
• Chương trình
Giải phương trình bằng phương pháp tiếp tuyến
NCT.FIT.HNUE 35
#include <iostream.h>
#include <math.h>
#include <iomanip.h>
float g(float x)
{return (x*x+1)/(2*x-1);}
void main(){
cout<<setiosflags(ios::showpo
int)<< setprecision(5);
float e, x0, x, epsilon;
x0=2; epsilon=0.001; e = 1;
while (e>epsilon)
{ x=g(x0);
e=fabs(x-x0); x0=x;
}
cout<<"x0="<<x0<<endl;
}
Lập trình giải quyết các bài toán sau
• Bài 1. Tính giá trị biểu thức sau:
a) Với giá trị của n được nhập từ bàn phím
b) Với số hạng cuối cùng của biểu thức là số hạng lớn nhất thỏa
mãn 1/(a+n) < , số được nhập từ bàn phím
• Bài 2. Một người gửi tiết kiệm có kì hạn với số tiền gửi ban đầu là
a đồng và lãi suất k% với chu kì tính lãi là c tháng. Việc tính lãi
suất có kì hạn được tích lũy.
a) Hãy tính số tiền nhận được sau khi gửi t tháng?
b) Hãy tính số tháng cần gửi để nhận được số tiền là b đồng?
Các số a, k, c, t, b được nhập từ bàn phím.
BÀI TẬP
NCT.FIT.HNUE 37
𝑆 = 𝑎 + 1
𝑎 + 1+
1
𝑎 + 2+ ⋯ +
1
𝑎 + 𝑛
Lập trình giải quyết các bài toán sau
• Bài 2. Tính nghiệm gần đúng của các phương trình sau bằng
phương pháp chia đôi và phương pháp tiếp tuyến với sai số cho
trước.
BÀI TẬP
NCT.FIT.HNUE 38
1) 𝑥 + 𝑒𝑥 = 0 2) 𝑥 − 𝑠𝑖𝑛𝑥 =1
5 3) 2 − ln 𝑥 − 𝑥 = 0
• Bài 3. Dùng các giá trị dưới đây của 𝑥 để tính giá trị gần đúng
của 3 bằng phương pháp nội suy Lagrange
x 1 2 4
𝑥 1 1.414 2
Lập trình giải quyết các bài toán sau
• Bài 4. Cho 33
trong bảng sau, dùng đa thức nội suy Newton để
tính 𝑥03 với x0 cho trước và x0 [8, 12] .
BÀI TẬP
NCT.FIT.HNUE 39
• Bài 5. Dân số của một quốc gia qua điều tra được cho trong bảng
sau, hãy ước lượng dân số của quốc gia này năm N, với N cho
trước và N [1960, 2000].
x 8 9 10 11 12
33
2 2.08 2.1544 2.224 2.2894
Năm 1960 1970 1980 1990 2000
Dân số 45 50.5 54 60.5 64
• Thuật toán tính giá trị gần đúng của đa thức nội suy Lagrange
GỢI Ý BÀI TẬP
NCT.FIT.HNUE 41
int main(){
int x[] = {1960,1970, 1980, 1990, 2000};
float y[] = {45, 50.5, 54, 60.5, 64};
cout<<setiosflags(ios::showpoint)<<setprecision(5);
float f, xx;
f=0; xx=1985;
int n=4;
for(int i=0;i<=n;i++){
float p=1;
for(int j=0;j<=n;j++)
if(j!=i) p*=(xx-x[j])/(x[i]-x[j]);
f+=y[i]*p;
}
cout<<"f("<<xx<<")="<<f<<endl; return 0;}
• Thuật toán tính giá trị gần đúng của đa thức nội suy Lagrange
GỢI Ý BÀI TẬP
NCT.FIT.HNUE 43
int main(){
int x[] = {1960,1970, 1980, 1990, 2000};
float f[] = {45, 50.5, 54, 60.5, 64};
cout<<setiosflags(ios::showpoint)<<setprecision(5);
float y=f[0], tich=1, xx =1985;
int n=4;
for(int i=1;i<=n;i++){
for(int j=0;j<=n-i;j++)
f[j]=(f[j+1]-f[j])/(x[j+i]-x[j]);
tich*=(xx-x[i-1]);
y+=tich*f[0];
}
cout<<"f("<<xx<<")="<<y<<endl; return 0;}
• Buổi sau kiểm tra ĐK lần 1
• 4 bài tập
– Bài 1: Tìm nghiệm gần đúng bằng phương pháp chia đôi
– Bài 2: Tìm nghiệm gần đúng bằng phương pháp tiếp tuyến
– Bài 3: Tính giá trị gần đúng của đa thức bằng phương pháp
Lagrange
– Bài 4: Tính giá trị gần đúng của đa thức bằng phương pháp
Newton
NHẮC LỚP
NCT.FIT.HNUE 44