带子程序的 C 程序
编程计算
其中( 0.3, ) / 2
( )2
f u x u up u
x
2 5( ) ( 2)
( 5) -
p x xy x p x
p x x
( , )7
w vf v w
v
void main(){ float y,f,p0,p2,p5,x;
printf ( "please input x: ");
scanf("%f",&x);
f=((x+x)+(x*0.3))/(7*(x*0.3));
p0=(f+x/2)/(2*x);
f=((x+(x+2))+((x+2)*0.3))/(7*((x+2)*0.3));
p2=(f+(x+2)/2)/(2*x);
f=((x+(x+5))+((x+5)*0.3))/(7*((x+5)*0.3));
p5=(f+(x+5)/2)/(2*x);
y=((p0*p0+5*x)/(p5-sqrt(x)))*p2;
printf ("y(x)=%8.4f\n",y);
}
0p p x0.3
( 0.3, )7 0.3
x x xf x x x
x
2 0.3 2 22 0.3, 2 2
7 2 0.3
x x xf x x x
x
2 2p p x
5 0.3 5 55 0.3, 5 5
7 5 0.3
x x xf x x x
x
5 5p p x
float x,y ; /* 3 */
float f(float v,float w ){ /* 4 */
return (w+v)/(7*v); /* 5 */
} /* 6 */
float p(float u){ /* 7 */
return ( f(u*0.3,x+u)+(u/2))/(2*x) ); /* 8 */
} /* 9 */
void main(){ /* 10 */
printf ("please input x: "); /* 11 */
scanf("%f",&x); /* 12 */
y=(p(x)*p(x)+(5*x))/(p(x+5)-sqrt(x))*p(x+2); /* 13 */
printf ("y(x)=%8.4f\n",y) /* 14 */
}
程序执行的主要步骤– 从键盘读入 x 的值
printf ("please input x: ");
scanf("%f",&x);
– 依次计算以 x, x+5, x+2 作为实参的函数 p 的值y=(p(x)*p(x)+(5*x))/(p(x+5)-sqrt(x))*p(x+2)
– 输入出函数 y 的值printf ("y(x)=%8.4f\n",y)
计算 p(x+5) 过程 – 计算 x+5 得 6.0 ;– 将 6.0 送入 p 的形参 u 中,这时 u 的值为 6.0 ;– 进入函数 p ,执行 p 的操作部分 ( 第 8 行 ), 即返回语句“ ret
urn ... ;” ,先计算返回语句中表达式的值。 以 u*0.3 和 u+x 为实参调用函数 f
– 顺序计算 u*0.3 、 u+x 得 1.8 、 7.0 ;– 将 1.8 、 7.0 顺序送入 f 的形参 v 、 w 中, v=1.8 、 w=7.0 ;– 进入函数 f 执行 f 的操作部分 ( 第 5 行 ) ,执行返回语句– 计算出表达式的值为 0.698413
– 带着函数值 0.698413 返回调用处, p 中的返回语句内 ( 第 8 行 )
计算出返回语句中表达式的值为 1.84921 即 p 的值。
– 带着函数值 1.84921 返回调用处:主程序第 13 行的表达式语句内。
函数 数学中函数
函数概念的组成
– 函数定义– 函数调用
使用函数注意事项– 先定义该函数(标准库函数除外)
——类似于数学中的函数定义。– 再在表达式中调用该函数
—— 数学中计算某函数的一个特定值。
yxyxf ),(
函数调用 (function-designator)
调用过程– 形参实参结合– 进入函数执行复合语句
一般形式– F (e, e, …, e)
– F ( )
例子– p (x+5)
– f (u*0.3,x+u)
函数定义 (function-declaration) 除标准库函数外 , 程序中使用函数必须先定义,然后
再用“函数调用”调用它。 标准函数是系统已经定义好的函数,不必定义即可直
接调用。 在程序 example401A中: float f(float v,float w ){ /* 4 */
return (w+v)/(7*v); /* 5 */
} /* 6 */
float p(float u){ /* 7 */
return ( f(u*0.3,x+u)+(u/2))/(2*x) ); /* 8 */
} /* 9 */
由上述语法可知,一个函数定义的形式是 :
类型说明符 标识符 ( 参数列表 ) 复合语句
float f (float u)
{
return (f(u*0.3,x+u)+(u/2))/(2*x);
}
函数类型
函数名字
形参列表复合语句
函数体函数定义说明符
函数定义说明符 上述形式的第一行称“函数定义说明符”,形式如
下 TT F ( 参数列表 )
具体指明以下点:函数的结果类型
——由“类型说明符” ( TT ) 标明;函数的名字
——由类型说明符后的“标识符” ( F ) 标明;函数的形式参数个数和每个形式参数的特性
—— 由“参数列表”标明。
函数类型(返回值的类型)– 不能是数组或函数– 没有返回值的函数类型是 void
函数返回– 返回方式:
return ;return 表达式;函数运行到复合语句末尾(最后那个闭
花括号“ }” )后。
参数列表 (parameter-list)
– 组成: 每个参数声明具体说明形式:
类型说明符 标识符 参数列表形式
T id , T id , ... , T id
– C 允许使用无参函数,无参函数的参数列表为空,或使用“空类型”的类型说明符“ void”
TT F() TT F (void )
int f(int x, int y, float z)int f(int x, int y, float z)
int f(int x,y ; float z)int f(int x,y ; float z)
int f(int x,y , float z)int f(int x,y , float z)
根据参数出现的位置– 形式参数——函数声明 ( 局部于函数的变量 )
int f(int x,int y){
return x+y;
}
– 实际参数——函数调用void main(){
int a=2,b=3;
f(a+b, b);
f(2+b,3);
}
3
int f (int x, int y){ return x*y;}void main(){
int a=3, b=2,x=9;int c;c=f(a+b,a+x);printf(“%d\n”, c);printf(“%d\n”, x);
} 2
9
程序输出为 :
60
9
a
b
x
返回值
x
y
c
main
f
内存
5
12
60
60
复合语句( compound-statement )由声明和语句列表组成
– 声明部分具体的说明本函数内使用的其它量;
– 语句部分规定在本函数中要执行的算法动作。 函数定义的形式:
TT F ( T id , T id , ... , T id ){
...
}
参数结合规则– 静态上看,实参表中的实参与被调用函数中形
参表的形参,按位置从左向右依次一一对应– 对应位置上的形实参间要赋值兼容– 各个实参的计算次序是依赖于实现的。
参数结合动作– 计算实参表达式的值– 把实参的值按赋值转换规则,转换成形参的类
型。如果不能完成该转换,则称函数参数不一致,产生错误
– 把转换后的实参值送入形参
0x
y
v
z
u
main
f
内存
……
g 返回值
返回值
由左至右#include "stdio.h"
int x,y ;
int f( int z ){
x=x+1 ;
return (z*z);
}
int g( int u , int v ){
… …
}
void main(){
x=0 ;
g(x,f(2)) ; }
0
2
1
4
4
0x
y
v
z
u
main
f
内存
……
g 返回值
返回值
由右至左#include "stdio.h"
int x,y ;
int f( int z ){
x=x+1 ;
return (z*z);
}
int g( int u , int v ){
… …
}
void main(){
x=0 ;
g(x,f(2)) ; }
1
2
1
4
4
并行计算 ----- 不知道结果#include "stdio.h"
int x,y ;
int f( int z ){
x=x+1 ;
return (z*z);
}
int g( int u , int v ){
… …
}
void main(){
x=0 ;
g(x,f(2)) ; }
函数值 有返回类型的函数 int f (int x, int y){
if (x>=y) return x; else return y;}
无返回类型的函数 void g( int w){
if (w==1) return; else x=3;}
有返回类型函数的函数值– 使用 return e; 向调用函数的主程序传递函数值– return e ; 的执行过程是:
计算表达式 e 的值 把表达式值按赋值转换规则,转换成函数的结
果类型; 返回语句中表达式的类型与函数的结果类型必
须赋值兼容。 用类型转换后的值作为函数值,并带着它返回
到调用该函数处
无返回类型函数的函数值void g( int w){
if (w==1) return; else x=3;}
在函数调用处,所调函数无值可以带回。– 对于无类型函数,在函数调用处不需要函数值,
这种返回是正常的;– 对于有类型函数,在函数调用处极可能需要函数
值参加下一步运算,这将带来不可预料的结果
一般形式TT F ( T , T , ... , T );
TT F ( T id , T id , ... , T id );
例子 float f ( int, float, int, char ) ;
float f ( int z, float u, int v, char w ) ;
float x,y ;
float f(float ,float );
float p(float );
void main(){
printf ("please input x: ");
scanf("%f",&x);
y=(p(x)*p(x)+(5*x))/(p(x+5)-sqrt(x))*p(x+2);
printf ("y(x)=%8.4f\n",y)
}
float f(float v,float w ){
return (w+v)/(7*v);
}
float p(float u){
return ( f(u*0.3,x+u)+(u/2))/(2*x) );
}
例 4-3 生成伪随机数
生成伪随机数公式
rk = ( multiplier * rk-1 + increment ) % modulus
如下给定三个常数值 , 产生 65536 个随机数multiplier = 25173
increment = 13849
modulus = 216 = 65536
#define multiplier 25173
#define increment 13849
#define modulus 65536
int seed=0 ;
int random ( void ) {
seed = ( multiplier * seed + increment ) % modulus ;
return seed ;
}
模拟掷骰子,函数修改成 :
int random ( void ) {
seed = ( multiplier * seed + increment ) % modulus ;
return seed % 6 +1 ;
}
产生 0 与 1 之间的实数型随机数序列,函数修改成 :
float random ( void ) {
seed = ( multiplier * seed + increment ) % modulus ;
return (float)seed / modulus;
}
例 4-4 验证 Pascal 定理 圆内接六边形三双对边延线的交点在一条直线上
A
BC
DE
F
B1
B2
B3
读入六个极角的值求六个顶点 A, B, C, D, E, F 在直角坐标系中的坐标
求三双对边交点 B1, B2, B3 坐标
验证 B1, B2, B3 是否在一条直线上
开始
结束
将 6 个点的极坐标转换成直角坐标
已知极角 theta,矢径 r,求一点的直角坐标 (px, py)
coordinate
px=r*cos(theta);
py=r*sin(theta);
return
trans_abcdef
转换 a → xa , ya
转换 b → xb , yb
转换 d → xd , yd
转换 f → xf , yf
转换 e → xe , ye
转换 c → xc , yc
return
求交点 B1,B2,B3 的坐标 已知四点 r, s, t, u求两条直线交点 B
three_inter
求 AB 、 DE交点 B1
求 BC 、 EF交点 B2
求 CD 、 FA交点 B3
return
intersection
求 r, s ; t, u直线方程 l1, l2
求 l1 、 l2交点 B
return
已知四点 r, s, t, u求两条直线 l1,l2 的方程
已知两点坐标 px, py, qx, qy, 求直线的斜率 a 和截距 b
eqution
return
求 r , s 直线方程 l1
求 t , u 直线方程 l2
straightline
b=(py*qx-qy*px)/(qx-px)
return
a=(py-qy)/(px-qx)
已知两条直线方程斜率分别为 ma, na; 截距mb, nb;求直线交点 (wx, wy)
验证 B1, B2, B3是否在一条直线上
inter
wx=(nb-mb)/(ma-na); wy=ma*px+mb;
return
test
return
求过 B1, B2 直线方程 L
判断 B3 是否在直线 L 上
/*PROGRAM Pascal theorem*/
#include "math.h"
#include "stdio.h"
#define PI 3.1415927
#define eps 1e-5
float radius; /* 圆的半径 */
float theta1, theta2, theta3, theta4, theta5, theta6;
/ * 六个极角的度数 */
float xa, ya, xb, yb, xc, yc, xd, yd, xe, ye, xf, yf;
/* 六个顶点的直角坐标 */
float b1_x, b1_y, b2_x, b2_y, b3_x, b3_y;
/* 三个交点的直角坐标 */
float b12_a, b12_b;
/*B1 和 B2 构成直线的斜率和截距 */
/* 主程序之前这段为“函数原型”以及各个函数返回结果所用变量 */
void trans_abcdef();
float px, py; /* 用来保存 coordinate() 转换的直角坐标 */
void coordinate (float, float);
void three_inter();
void intersection (float, float, float, float, float, float, float, float);
float l1_a, l1_b, l2_a, l2_b; /* 两条直线的斜率和截距 */
void equation (float, float, float, float, float, float, float, float);
float a, b; /* 直线方程的斜率和截距 */
void straightline(float, float, float, float);
float wx, wy; /* 直线交点的直角坐标 */
void inter (float, float, float, float);
int test (float, float, float, float, float, float);
/* 主函数 */void main(){ /* 读入圆形的半径 */ printf("please input the radius of the circle:"); scanf("%f", &radius); /* 读入六个角 */ printf("please input six angle:"); scanf("%f %f %f %f %f %f", &theta1, &theta3, &theta3, &theta4, &theta5, &theta6); trans_abcdef(); /* 计算六个定点坐标 */ three_inter(); /* 求三个交点 */ if( test(b1_x, b1_y, b2_x, b2_y, b3_x, b3_y) ) /*验证 */ printf("ok"); else{ printf("There is an error when:\n"); printf("theta1=%d theta2=%d\n", theta1, theta2); printf("theta3=%d theta4=%d\n", theta3, theta4); printf("theta5=%d theta6=%d\n", theta5, theta6); }}
/* 计算六个顶点坐标 */
void trans_abcdef(){
coordinate(radius, theta1);
xa=px; ya=py;
coordinate(radius, theta2);
xb=px; yb=py;
coordinate(radius, theta3);
xc=px; yc=py;
coordinate(radius, theta4);
xd=px; yd=py;
coordinate(radius, theta5);
xe=px; ye=py;
coordinate(radius, theta6);
xf=px; yf=py;
}
/* 计算一个顶点坐标 */
void coordinate(float r, float theta) {
/* 先把“角度”转换成“弧度”,再转换成直角坐标 */
px=r*cos(PI*theta/180);
py=r*sin(PI*theta/180);
}
/*求三个交点 */
void three_inter(){
intersection(xa, ya, xb, yb, xd, yd, xe, ye);
b1_x=wx; b1_y=wy;
intersection(xb, yb, xc, yc, xe, ye, xf, yf);
b2_x=wx; b2_y=wy;
intersection(xc, yc, xd, yd, xf, yf, xa, ya);
b3_x=wx; b3_y=wy;
}
/* 已知四点,求两条直线交点 */
void intersection(float rx, float ry, float sx, float sy,
float tx, float ty, float ux, float uy){
equation (rx, ry, sx, sy, tx, ty, ux, uy);
inter (l1_a, l1_b, l2_a, l2_b);
}
/* 已知四点,求两条直线方程 */
void equation ( float rx, float ry, float sx, float sy,
float tx, float ty, float ux, float uy){
straightline(rx, ry, sx, sy);
l1_a=a; l1_b=b;
straightline(tx, ty, ux, uy);
l2_a=a; l2_b=b;
}
/* 计算由两点确定直线方程的斜率( a )和截距( b ) */
void straightline(float ex, float ey, float fx, float fy){
a=(fy-ey)/(fx-ex); /* 斜率 */
b=ey-a*ex; /* 截距 */
}
/* 已知两个直线方程的斜率和截距,求它们交点 */
void inter ( float ma, float mb, float na, float nb){
wx=(nb-mb)/(ma-na);
wy=ma*wx+mb;
}
/* 检验 */
bool test ( float b1_x, float b1_y,
float b2_x, float b2_y,
float b3_x, float b3_y) {
straightline(b1_x, b1_y, b2_x, b2_y);
if(fabs(b3_y-(a*b3_x+b))<eps)
return true;
else
return false;
}
Top Related