1
四,break语句与 continue语句五,goto 语句六、多重循环七、梯形法求积分算例
2
四,break语句与 continue语句前面三种循环结构都以某个表达式的判断结果作为循环条件,当表达式的值为零时,就立即结束循环。
这是一种遇零就结束循环的简短直接的判断。
C/C++另外提供了 break语句,continue语句与 goto 语句来改变循环的转向。
break与 continue语句用在 while,do~while和 for循环中,break尚可用于 switch 语句。
break语句与 continue语句的语法格式非常简单,各在其关键字后跟随一个分号,
break;
或 continue;
3
(1)while语句 (2)for语句 (3) do~ while语句非零
while
零循环体
[ break;]
...
[continue;]
....
后续语句表达式后续语句增量表达式循环体
[ break;]
...
[continue;]
....
零非零
for
初始表达式表达式零后续语句非零循环体
...
[ break;]
...
[continue;]
....
do
表达式
wh
ile
4
1.break语句用于退出循环体或 switch语句,在多重循环或 switch语句的嵌套中 break语句仅只终止最紧密包含它的循环体或
switch语句,控制跳转到当前层的循环体或 switch语句的后续语句 ;
2.continue语句仅位于循环语句的循环体中,忽略跟随其后的剩余语句,然后判断是否继续下一轮的循环,它的作用不是结束循环迭代,而是退出本次循环,继续下一轮的循环 ;
对于 while和 do~while循环 continue语句跳到循环的底部或立即执行条件测试,对于常规的 for循环,执行增量表式之后再继续下一个回合的条件判断。
5
for循环和 while循环具有下面的相当的关系:
for(初始化表达式 ;条件表达式 ;增量表达式 )
{循环体语句 ;}
for (initialexpre; conditionexpre; stepexpre)
{ statement; }
相当于下面 while循环,
initialexpre; while (conditionexpre)
{ statement; stepexpre; }
初始化表达式 ; while (条件表达式 )
{ 循环体语句 ; 增量表达式 ; }
但 continue语句隐含地执行 for循环的增量表达式。如果 while循环中的增量表达式位于 continue语句之后,此时这个增量表达式 stepexpre可以不执行。这是两者不同之处。
6
常规形式:
for (initexpre;conditionexpre;stepexpre)
{ statement;}
# include<iostream.h> //求自然数的和
void main (void)
{ int sum=0;
for (int k=0; k<=100; sum+=k++); // 循环体的语句为空语句
cout<<sum <<endl;
} //输出 5050
7
初始化表达式前置:
initexpre;for ( ; conditionexpre; stepexpre)
{ statement; }
# include<iostream.h>
int sum ( int k )
//此种形式用于函数体中,初始值直接从形参中获得
{ int s=0;
for ( ; k<=100;s+=k++) ; //循环体的语句为空语句
return s; }
void main (void) { cout<<sum (10) <<endl; }
//输出 5005
8
条件表达式内置 (目的是灵活控制循环的跳出件 ):
for (initexpre ; ; stepexpr)
{ if(condition1==0) break;
//条件 1为 0跳出循环
statement; //条件 1非 0继续循环
if(condition2) break;
//条件 2为非 0跳出循环
} //for ( initexpre ; ; stepexpr )等价于
for(initexpre ; 1 ; stepexpr)
此时如果 for循环中没有相应的跳出条件,则构成无穷循环。
9
[例 ]输出奇数 [例 2]输出偶数
# include<iostream.h> # include<iostream.h>
void main (void) void main(void)
{ for(int k=1;k<10;k++) { for (int k=1;;k++){
{ if (k%2==0) continue; if (k%2==0) {cout<<k<<",";
continue; }
cout<<k<<","; if (k>10) break;
} }
} }
/*输出,1,3,5,7,9,*/ //输出,2,4,6,8,10,
10
条件表达式内置与增量表达式内置
[例 ]输出奇数 [例 ]输出偶数
# include<iostream.h> # include<iostream.h>
void main (void) void main (void)
{ for (int k=0;;) { for (int k=0;;)
{ k++; { k++;
if (k<10) if (k%2==0)
{if(k%2){cout<<k; continue;}} {cout<<k; continue;}
else break; if (k>10) break;
} }
}//输出,246810 }//输出,13579
11
无穷循环 for (;;)
# include<iostream.h>
void main(void)
{ int k=0,sum=0; // initexpre;
for(; ;) //for (;;)
{ if( k>100) break;
//{ if(condition) break;条件判断为真退出循环
sum+=k;
// statement; 条件判断为 0执行循环体
k++; // stepexpre; 循环步长增量变动
}
cout<<sum <<endl; /*输出 5050*/
}
12
五,goto 语句要求和标号配合及使用的格式如下:
goto 标号; goto label;
标号:语句; label,statement; goto语句
goto语句要求和标号配合;其中标号的命名遵循标识符的规定。
goto语句的功能是把程序控制转移到标号指定的语句,即执行 goto语句之后,程序从指定标号处的语句继续执行标号表明程序中代码段的某个位置。
标号加在某个执行语句的前面,其后面使用冒号,:”作为分隔符。
13
[例 ] for循环与 if~goto label 循环比较
1.if~goto label 循环求和 2.goto 语句循环求和
# include<iostream.h> int sum (int n=100)
void main (void) { int k=1,s=0;
{ int k=0,sum=0; loop:
loop,if (k<=n)
if(k>100) goto end; { s+=k++;
sum+=k++; goto loop;
goto loop; }
end,cout <<sum <<endl; return s;
} /*输出 5050*/ }
14
3,if~goto label 循环求和
# include<iostream.h>
void main (void)
{ int k=0,sum=0;
loop,
if (k>100) goto end;
sum+=k++;
goto loop;
end:cout << sum << endl;
} /*输出 5050*/
15
六、多重循环多重循环结构指在循环体中的复合语句是另外一个循环控制结构,形成循环的多层次的嵌套。
C/C++中三种循环可以互相渗透互相包含,也可以自身嵌套如,
while(e4) statement ;
while(e) while(e4) statement ;
for (e1;e2;e3) while(e4) statement;
while(e) for (e1;e2;e3) while(e4) statement;
do { do { statement;} while(e1);} while(e2);
while(e) do do statement; while(e1); while(e2);
16
每一个循环控制结构本身应是一个完整的循环语句,同时完整的循环语句可以视为一条简单的语句。单一语句可以出现的场所,完整的循环语句也可以恰当地嵌入。
循环嵌套时外层的循环控制变量常作为内层的循环控制体相关变量的初值。
不要在内层轻易改变外层循环的增量控制条件。
for循环语句 [ for (e1; e2; e3) s; ]中的语句是另外一个
for循环语句这样就得到双重 for循环:
for ( e1;e2;e3 ) for ( e4;e5;e6 ) statement;
17
[例 ] 求的 和,误差小于指定精度 eps
#include<stdio.h>
#include<math.h>
const double e=exp(1);
double expf ()
{ double const eps=1.0e-19;
double sum=1; int n=1;
while (e - sum> eps)
!n1...!21!111e
18
{ double facn=1;
for (int i=1; i<=n; i++) facn *=i;
sum+=1.0/facn; n++; }
return sum;
}
void main( )
{ printf ("e=%lf,es=%lf\t",e,expf ()); }
上面 while(e-sum>eps) 条件判断中的 e=exp(1),如果写为 while (exp(1)- sum > eps)则每次判断时都需执行函数
exp(1)求值计算。
对于与循环无关的函数调用应先计算出其值,以减少不必要的重复计算。
19
七、梯形法求积分算例将一个区间 [a,b]分成 n个子区间:
其中下面是积分的定义:
积分如果右边的极限存在,其极限值就是定积分的结果。
理论上区间分得越细越逼近理论的解,但计算机求和次数过多导致的计算误差不容小视。
[,],[,],.,,,[,]x x x x x xn n0 1 1 2 1?
x a x bn0,
I f x dx f x xxn mkna b k ( ) lim ( )0 0
20
在计算机进行离散处理时应考虑两方面因素:
一是区间适当细分;
二是收敛性的精度限制。
区间的划分存在两种途径:
一是静态地将区间分为 n等分,n是预先定好的整数;
另一种是动态地确定区间划分数,将区间根据某种细分机制,逐步细分,最终的区间划分数根据收敛指标动态确定。
21
下面介绍的梯形算法属于区间一分为二的动态等分,包含复杂求积算法的基本要素。梯形法的求解步骤为:
(1)首先分成一个区间时积分值为,
h=b-a,T2=0
上面的关系作为迭代的初始值。
T h f a f b1 2( ( ) ( ))
a b x
y
22
(2)分成两个相等的子区间时积分值为,
h x a b x h1 1 1 2
x a h1 2
T h f a f x h f x f b T h f x2 1 1 1 1 1 12 2 12 2( ( ) ( )) ( ( ) ( )) ( )
ba x
y
x1
23
(3)当分成相等的子区间时积分值为,
T h f x f xnk k k
n
1 0
2 1
12
[ ( ) ( )]
h x x hn k k n1 1 2/
xk xk1 x
y
24
(4)进一步将上面个相等的每一个子区间一分为二,对于每一新的子区间采用梯形计算公式,其结果用前一个回合的区间边界值予以表示得到,
这样就得到迭代关系式,
T h f x f x T h f x hnk k k n k nkn n2 102 1 1 1 02 12 12 2 0 51[ ( ) ( )] (,)' '
sum f x hk hk n (,)0 502 1
T T h sumn2 112( )
x
y
x xk k' '?1
25
(5) 迭代的收敛准则。迭代根据一个精度指标限定,满足这个指标认为计算收敛,这个指标为:
即相邻两次迭代求得的积分值之差小于一个非常小的
eps,则认为此时求得的就是所求的结果。
如果不满足收敛指标则继续迭代,即将区间的分点加密一倍。
迭代不一定收敛,因此通常内置一个最大迭代次数。如果超过最个迭代次数依然未得到正常的收敛结果,应考虑采取相关的手段。
如调整精度指标 eps,过小的 eps非但得不到合理的计算结果反而因为计算的累计误差而发散。
T T eps2 1
26
[例 ] 梯形求积算法
#include <math.h>
# include<stdio.h>
extern double f(double); //函数原型说明
double Trapzoidal (double a,double b,
const double eps=1.0e-8)
{ double h=b - a;
double T1=0.5*h*(f(a)+f(b));
double T2=0;
const int MaxIteration=0x7000;
27
for (int n=1;n<MaxIteration;n*=2)
{ double sum=0;
double x=a+0.5*h;
for ( int k=0; k<n; k++,x+=h) sum+=f(x);
T2=0.5*(T1+h*sum);
if(fabs(T2-T1)<eps) return T2;
T1=T2;
h/=2;
}
printf ("Epsilon is too small\n");
return MaxIteration;
}
28
Trapzoidal函数第三个形参 eps声明为
const double eps=1.0e-8,这是程序员对于函数使用者的一个缺省建议,收敛指标 eps取值于 1.0e-8附近,函数容易收敛。带缺省值的参数是 C++新引进的语法现象。
上面的 Trapzoidal函数通过两个被积函数进行具体算题考核,它们分别是:
f(x)=1+x
精度指标 eps影响函数 的积分收敛性,对于线性函数无影响。
f x e x
x
( ),2 5 2
f x e xx( ) / (,)2 5 2
29
[例 ]被积函数为
double f(double x)
{ return exp(x)/(2.5+x*x); }
void main (void)
{
printf("%f\n",Trapzoidal(1,2,1.0e-7));
printf("%f\n",Trapzoidal(1,2,1.0e-13));
}
被积函数为输出结果为
0.947938
Epsilon is too small
28672.000000
e xx / (,)2 5 2?
30
[例 ] 被积函数为 1+x
double f(double x)
{return (1+x); }
void main (void)
{ printf("%f\n",Trapzoidal(1,2,1.0e-1));
printf("%f\n",Trapzoidal(1,2,1.0e-23));
printf("%f\n",Trapzoidal(1,2,1.0e-123));
}
被积函数为 1+x输出结果为:
2.500000
2.500000
2.500000
31
四,break语句与 continue语句五,goto 语句六、多重循环七、梯形法求积分算例
2
四,break语句与 continue语句前面三种循环结构都以某个表达式的判断结果作为循环条件,当表达式的值为零时,就立即结束循环。
这是一种遇零就结束循环的简短直接的判断。
C/C++另外提供了 break语句,continue语句与 goto 语句来改变循环的转向。
break与 continue语句用在 while,do~while和 for循环中,break尚可用于 switch 语句。
break语句与 continue语句的语法格式非常简单,各在其关键字后跟随一个分号,
break;
或 continue;
3
(1)while语句 (2)for语句 (3) do~ while语句非零
while
零循环体
[ break;]
...
[continue;]
....
后续语句表达式后续语句增量表达式循环体
[ break;]
...
[continue;]
....
零非零
for
初始表达式表达式零后续语句非零循环体
...
[ break;]
...
[continue;]
....
do
表达式
wh
ile
4
1.break语句用于退出循环体或 switch语句,在多重循环或 switch语句的嵌套中 break语句仅只终止最紧密包含它的循环体或
switch语句,控制跳转到当前层的循环体或 switch语句的后续语句 ;
2.continue语句仅位于循环语句的循环体中,忽略跟随其后的剩余语句,然后判断是否继续下一轮的循环,它的作用不是结束循环迭代,而是退出本次循环,继续下一轮的循环 ;
对于 while和 do~while循环 continue语句跳到循环的底部或立即执行条件测试,对于常规的 for循环,执行增量表式之后再继续下一个回合的条件判断。
5
for循环和 while循环具有下面的相当的关系:
for(初始化表达式 ;条件表达式 ;增量表达式 )
{循环体语句 ;}
for (initialexpre; conditionexpre; stepexpre)
{ statement; }
相当于下面 while循环,
initialexpre; while (conditionexpre)
{ statement; stepexpre; }
初始化表达式 ; while (条件表达式 )
{ 循环体语句 ; 增量表达式 ; }
但 continue语句隐含地执行 for循环的增量表达式。如果 while循环中的增量表达式位于 continue语句之后,此时这个增量表达式 stepexpre可以不执行。这是两者不同之处。
6
常规形式:
for (initexpre;conditionexpre;stepexpre)
{ statement;}
# include<iostream.h> //求自然数的和
void main (void)
{ int sum=0;
for (int k=0; k<=100; sum+=k++); // 循环体的语句为空语句
cout<<sum <<endl;
} //输出 5050
7
初始化表达式前置:
initexpre;for ( ; conditionexpre; stepexpre)
{ statement; }
# include<iostream.h>
int sum ( int k )
//此种形式用于函数体中,初始值直接从形参中获得
{ int s=0;
for ( ; k<=100;s+=k++) ; //循环体的语句为空语句
return s; }
void main (void) { cout<<sum (10) <<endl; }
//输出 5005
8
条件表达式内置 (目的是灵活控制循环的跳出件 ):
for (initexpre ; ; stepexpr)
{ if(condition1==0) break;
//条件 1为 0跳出循环
statement; //条件 1非 0继续循环
if(condition2) break;
//条件 2为非 0跳出循环
} //for ( initexpre ; ; stepexpr )等价于
for(initexpre ; 1 ; stepexpr)
此时如果 for循环中没有相应的跳出条件,则构成无穷循环。
9
[例 ]输出奇数 [例 2]输出偶数
# include<iostream.h> # include<iostream.h>
void main (void) void main(void)
{ for(int k=1;k<10;k++) { for (int k=1;;k++){
{ if (k%2==0) continue; if (k%2==0) {cout<<k<<",";
continue; }
cout<<k<<","; if (k>10) break;
} }
} }
/*输出,1,3,5,7,9,*/ //输出,2,4,6,8,10,
10
条件表达式内置与增量表达式内置
[例 ]输出奇数 [例 ]输出偶数
# include<iostream.h> # include<iostream.h>
void main (void) void main (void)
{ for (int k=0;;) { for (int k=0;;)
{ k++; { k++;
if (k<10) if (k%2==0)
{if(k%2){cout<<k; continue;}} {cout<<k; continue;}
else break; if (k>10) break;
} }
}//输出,246810 }//输出,13579
11
无穷循环 for (;;)
# include<iostream.h>
void main(void)
{ int k=0,sum=0; // initexpre;
for(; ;) //for (;;)
{ if( k>100) break;
//{ if(condition) break;条件判断为真退出循环
sum+=k;
// statement; 条件判断为 0执行循环体
k++; // stepexpre; 循环步长增量变动
}
cout<<sum <<endl; /*输出 5050*/
}
12
五,goto 语句要求和标号配合及使用的格式如下:
goto 标号; goto label;
标号:语句; label,statement; goto语句
goto语句要求和标号配合;其中标号的命名遵循标识符的规定。
goto语句的功能是把程序控制转移到标号指定的语句,即执行 goto语句之后,程序从指定标号处的语句继续执行标号表明程序中代码段的某个位置。
标号加在某个执行语句的前面,其后面使用冒号,:”作为分隔符。
13
[例 ] for循环与 if~goto label 循环比较
1.if~goto label 循环求和 2.goto 语句循环求和
# include<iostream.h> int sum (int n=100)
void main (void) { int k=1,s=0;
{ int k=0,sum=0; loop:
loop,if (k<=n)
if(k>100) goto end; { s+=k++;
sum+=k++; goto loop;
goto loop; }
end,cout <<sum <<endl; return s;
} /*输出 5050*/ }
14
3,if~goto label 循环求和
# include<iostream.h>
void main (void)
{ int k=0,sum=0;
loop,
if (k>100) goto end;
sum+=k++;
goto loop;
end:cout << sum << endl;
} /*输出 5050*/
15
六、多重循环多重循环结构指在循环体中的复合语句是另外一个循环控制结构,形成循环的多层次的嵌套。
C/C++中三种循环可以互相渗透互相包含,也可以自身嵌套如,
while(e4) statement ;
while(e) while(e4) statement ;
for (e1;e2;e3) while(e4) statement;
while(e) for (e1;e2;e3) while(e4) statement;
do { do { statement;} while(e1);} while(e2);
while(e) do do statement; while(e1); while(e2);
16
每一个循环控制结构本身应是一个完整的循环语句,同时完整的循环语句可以视为一条简单的语句。单一语句可以出现的场所,完整的循环语句也可以恰当地嵌入。
循环嵌套时外层的循环控制变量常作为内层的循环控制体相关变量的初值。
不要在内层轻易改变外层循环的增量控制条件。
for循环语句 [ for (e1; e2; e3) s; ]中的语句是另外一个
for循环语句这样就得到双重 for循环:
for ( e1;e2;e3 ) for ( e4;e5;e6 ) statement;
17
[例 ] 求的 和,误差小于指定精度 eps
#include<stdio.h>
#include<math.h>
const double e=exp(1);
double expf ()
{ double const eps=1.0e-19;
double sum=1; int n=1;
while (e - sum> eps)
!n1...!21!111e
18
{ double facn=1;
for (int i=1; i<=n; i++) facn *=i;
sum+=1.0/facn; n++; }
return sum;
}
void main( )
{ printf ("e=%lf,es=%lf\t",e,expf ()); }
上面 while(e-sum>eps) 条件判断中的 e=exp(1),如果写为 while (exp(1)- sum > eps)则每次判断时都需执行函数
exp(1)求值计算。
对于与循环无关的函数调用应先计算出其值,以减少不必要的重复计算。
19
七、梯形法求积分算例将一个区间 [a,b]分成 n个子区间:
其中下面是积分的定义:
积分如果右边的极限存在,其极限值就是定积分的结果。
理论上区间分得越细越逼近理论的解,但计算机求和次数过多导致的计算误差不容小视。
[,],[,],.,,,[,]x x x x x xn n0 1 1 2 1?
x a x bn0,
I f x dx f x xxn mkna b k ( ) lim ( )0 0
20
在计算机进行离散处理时应考虑两方面因素:
一是区间适当细分;
二是收敛性的精度限制。
区间的划分存在两种途径:
一是静态地将区间分为 n等分,n是预先定好的整数;
另一种是动态地确定区间划分数,将区间根据某种细分机制,逐步细分,最终的区间划分数根据收敛指标动态确定。
21
下面介绍的梯形算法属于区间一分为二的动态等分,包含复杂求积算法的基本要素。梯形法的求解步骤为:
(1)首先分成一个区间时积分值为,
h=b-a,T2=0
上面的关系作为迭代的初始值。
T h f a f b1 2( ( ) ( ))
a b x
y
22
(2)分成两个相等的子区间时积分值为,
h x a b x h1 1 1 2
x a h1 2
T h f a f x h f x f b T h f x2 1 1 1 1 1 12 2 12 2( ( ) ( )) ( ( ) ( )) ( )
ba x
y
x1
23
(3)当分成相等的子区间时积分值为,
T h f x f xnk k k
n
1 0
2 1
12
[ ( ) ( )]
h x x hn k k n1 1 2/
xk xk1 x
y
24
(4)进一步将上面个相等的每一个子区间一分为二,对于每一新的子区间采用梯形计算公式,其结果用前一个回合的区间边界值予以表示得到,
这样就得到迭代关系式,
T h f x f x T h f x hnk k k n k nkn n2 102 1 1 1 02 12 12 2 0 51[ ( ) ( )] (,)' '
sum f x hk hk n (,)0 502 1
T T h sumn2 112( )
x
y
x xk k' '?1
25
(5) 迭代的收敛准则。迭代根据一个精度指标限定,满足这个指标认为计算收敛,这个指标为:
即相邻两次迭代求得的积分值之差小于一个非常小的
eps,则认为此时求得的就是所求的结果。
如果不满足收敛指标则继续迭代,即将区间的分点加密一倍。
迭代不一定收敛,因此通常内置一个最大迭代次数。如果超过最个迭代次数依然未得到正常的收敛结果,应考虑采取相关的手段。
如调整精度指标 eps,过小的 eps非但得不到合理的计算结果反而因为计算的累计误差而发散。
T T eps2 1
26
[例 ] 梯形求积算法
#include <math.h>
# include<stdio.h>
extern double f(double); //函数原型说明
double Trapzoidal (double a,double b,
const double eps=1.0e-8)
{ double h=b - a;
double T1=0.5*h*(f(a)+f(b));
double T2=0;
const int MaxIteration=0x7000;
27
for (int n=1;n<MaxIteration;n*=2)
{ double sum=0;
double x=a+0.5*h;
for ( int k=0; k<n; k++,x+=h) sum+=f(x);
T2=0.5*(T1+h*sum);
if(fabs(T2-T1)<eps) return T2;
T1=T2;
h/=2;
}
printf ("Epsilon is too small\n");
return MaxIteration;
}
28
Trapzoidal函数第三个形参 eps声明为
const double eps=1.0e-8,这是程序员对于函数使用者的一个缺省建议,收敛指标 eps取值于 1.0e-8附近,函数容易收敛。带缺省值的参数是 C++新引进的语法现象。
上面的 Trapzoidal函数通过两个被积函数进行具体算题考核,它们分别是:
f(x)=1+x
精度指标 eps影响函数 的积分收敛性,对于线性函数无影响。
f x e x
x
( ),2 5 2
f x e xx( ) / (,)2 5 2
29
[例 ]被积函数为
double f(double x)
{ return exp(x)/(2.5+x*x); }
void main (void)
{
printf("%f\n",Trapzoidal(1,2,1.0e-7));
printf("%f\n",Trapzoidal(1,2,1.0e-13));
}
被积函数为输出结果为
0.947938
Epsilon is too small
28672.000000
e xx / (,)2 5 2?
30
[例 ] 被积函数为 1+x
double f(double x)
{return (1+x); }
void main (void)
{ printf("%f\n",Trapzoidal(1,2,1.0e-1));
printf("%f\n",Trapzoidal(1,2,1.0e-23));
printf("%f\n",Trapzoidal(1,2,1.0e-123));
}
被积函数为 1+x输出结果为:
2.500000
2.500000
2.500000
31