1 / 43

计算方法上机基础篇

计算方法上机基础篇. 应用于 C/C++ 语言程序设计. 华中科技大学数学与统计学院计算数学系. 科技楼南 836 室. 何南忠. QQ : 2121211. nzhe@163.com. http : //math.hust.edu.cn/he. 作者 : 从事于计算数学、高性能计算、 LBGK 及软件开发。. 2008-12. 第 01 章 数值、运算与程序. 数 – 分类. 数值计算中常用的 2 类. 整数 :. 无 小数点. ± 0 ± 1 ± 2 ± 3.

kailey
Download Presentation

计算方法上机基础篇

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 计算方法上机基础篇 应用于C/C++语言程序设计 华中科技大学数学与统计学院计算数学系 科技楼南836室 何南忠 QQ: 2121211 nzhe@163.com http://math.hust.edu.cn/he 作者: 从事于计算数学、高性能计算、LBGK及软件开发。 2008-12

  2. 第01章 数值、运算与程序

  3. 数 – 分类 数值计算中常用的2类 整数: 无小数点 ±0 ±1±2±3 ... ±0.±0.1 ±1.±1.2 ±2.±2.3 ±3.... 实数: 有小数点 练习:

  4. 数 – 范围 整数: 内部表示为32位二进制整数 ±2147483647= ±231-1 实数: 内部表示为二个整数: ±0.999999999999999E±308 第一个整数表示小数部分, 第二个整数表示指数部分; 共占64个二进制位。 小数 指数 (小数54bits, 指数10bits)

  5. 数 – 精度 整数: 对小数取整; 超过范围取231的余数。 ±2147483647=±231-1 0.123456789012345E-10 实数: 15位后舍去; 超过范围则溢出报错。 小数部分15位 练习:

  6. 数 – 运算 + - * / 结果为整数 整数: 3 / 2 = 1 结果为实数 实数: 3.0 / 2.0 = 1.5 结果为实数 3.0 / 2 = 3 / 2.0 = 1.5 混合: 整数运算还有: % << >> & | ! ^ 取余数 左移 右移 按位与 按位或 按位反 按位异或 练习:

  7. 数–算术运算表达式 先*/后+-, 从左到右, 括号优先。 练习:

  8. 变量: 存贮一个数, 并能被取出来使用这个数 A, A1, B, B123, abc, ... 起名: 首字符为字母, 后面字母或数字 变量使用前要先定义, 定义用类型定义语句: 定义: 类型名 变量名; int A; 例: double B; 变量的使用包括存和取, 存用赋值语句: 使用: 变量名= 表达式; 而表达式中出现的变量名即为取变量的值。

  9. 程序: 语句序列 //先定义: int A; //名字为 A, 值的类型为 整数 double B; //名字为 B, 值的类型为 实数 //后使用: A = 10; //A: 10 B = 10.0; //B: 10.0 A = A + 1;//A: 11 B = A - B;//B: 1.0 ... 1. 类型定义语句 类型名 变量名; 2. 赋值语句 变量名 = 表达式; 取 存 赋值运算符 一行中//后面的为注释, 不起作用

  10. 程序: 完整结构 void main() { int A; double B; A = 10; B = 10.0; A = A + 1; B = A - B; int A; double B; A = 10; B = 10.0; A = A + 1; B = A - B; 执 打包 行 } 一个程序中有且仅有一个main函数; 程序从main函数中的第一行开始执行。 main函数:

  11. 键盘输入语句: 从键盘上输入一个或几个数到变量。 int A; scanf( ”%d”, &A ); ; -仅用于一条简单语句的结束 double B; scanf( ”%lf”, &B ); , -常用于分隔 int A, B; // 多个变量用,分隔之 double C,D; // 多个变量用,分隔之 scanf( ”%d%lf%d%lf”, &A, &C, &B, &D ); 地址列表 格式串 &变量名–表示该变量的地址

  12. 屏幕输出语句: 把字符串、数值显示到屏幕上。 printf( ”Hello, World!” ); 结果: Hello, World! int A; A = 100; printf( ”A =%d”, A+1 ); 结果: A =101 int A, B; double C, D; A = 100; B = A + 100; C = B + 100; D = C + 100; printf( ”A=%d,B=%d,C=%lf,D=%lf”,A+1, B+2, C+3, D+4 ); 值列表 格式串 一一对应 结果: A=101,B=202,C=303.0,D=404.0

  13. 程序1: 输出一个字符串的最简单程序。 #include <stdio.h> // 输入输出语句所在头文件 void main( ) { } printf( ”Hello, World!” ); 运行结果:

  14. 程序2: 变量赋一个值后输出该变量的值。 #include <stdio.h> void main() { int A; A = 100; printf( ”A = %d”, A ); } 运行结果:

  15. 程序3: 几个变量赋值后输出这几个变量的值。 #include <stdio.h> void main() { int A, B; double C, D; A = 100; B = A + 100; C = B + 100; D = C + 100; printf( ”A=%d,B=%d,C=%lf,D=%lf”, A, B, C, D ); } 运行结果:

  16. 程序4: 输入2个整数, 输出相加、相减、相乘和相除的结果。 #include <stdio.h> void main() { int A, B; scanf( ”%d%d”, &A, &B ); printf( ”%d + %d=%d”, A, B, A + B ); printf( ”%d - %d=%d”, A, B, A - B ); printf( ”%d * %d=%d”, A, B, A * B ); printf( ”%d / %d=%d”, A, B, A / B ); } 运行结果:

  17. 程序5: 输入2个实数, 输出相加、相减、相乘和相除的结果。 #include <stdio.h> void main() { int A, B; scanf( ”%lf%lf”, &A, &B ); printf( ”%lf + %lf=%lf”, A, B, A + B ); printf( ”%lf - %lf=%lf”, A, B, A - B ); printf( ”%lf * %lf=%lf”, A, B, A * B ); printf( ”%lf / %lf=%lf”, A, B, A / B ); } 运行结果:

  18. 程序6: 输入2个实数, 输出相加、相减、相乘和相除的结果的整数值。 #include <stdio.h> void main() { int A, B; scanf( ”%lf%lf”, &A, &B ); printf( ”%lf + %lf=%lf”, A, B, (int)(A + B ); printf( ”%lf - %lf=%lf”, A, B, (int)(A - B ); printf( ”%lf * %lf=%lf”, A, B, (int)(A * B ); printf( ”%lf / %lf=%lf”, A, B, (int)(A / B ); } 运行结果: (int)实数的结果为整数 (double)整数的结果为实数 这叫类型强制转换

  19. 程序7: 输入10个整数, 输出其和及平均值。 #include <stdio.h> void main() { int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9; int sum; printf( ”Enter 10 numbers: ”); scanf( ”%d%d%d%d%d%d%d%d%d”, &i0, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9); sum = i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9; printf( “sum is %d\n”, sum, x ); // \n – 换行符 printf( “average is %lf”, sum / 10.0 ); } 运行结果:

  20. 程序8: 输入1个实数, 输出其平方根。 #include <stdio.h> void main() { double a; double x; scanf( ”%lf”, &a ); x = a; x = ( x + a / x ) / 2; x = ( x + a / x ) / 2; x = ( x + a / x ) / 2; x = ( x + a / x ) / 2; x = ( x + a / x ) / 2; // 要准确, 则再重复100行 printf( “square root of %lf = %lf”, a, x ); } 运行结果:

  21. 程序9: 输入3个实数a、b、c, 输出ax2+bx+c=0的二个根。 #include <stdio.h> void main() { double a, b, c, d, d1; printf( ”Input a,b,c : ” ); scanf( ”%lf%lf%lf”, &a, &b, &c ); d = b*b – 4*a*c; d1 = d; d1 = ( d1 + d / d1 ) / 2; d1 = ( d1 + d / d1 ) / 2; d1 = ( d1 + d / d1 ) / 2; d1 = ( d1 + d / d1 ) / 2; d1 = ( d1 + d / d1 ) / 2; d1 = ( d1 + d / d1 ) / 2; printf( “x1 = %lf, x2 = %lf”, (-b+d1)/(2*a), (-b-d1)/(2*a) ); } 运行结果:

  22. 程序10: 输入3个实数a、b、c, 输出ax2+bx+c=0的二个根。 #include <stdio.h> #include <math.h> void main() { double a, b, c, d, d1; printf( ”Input a,b,c :” ); scanf( ”%lf%lf%lf”, &a, &b, &c ); d = b*b – 4*a*c; d1 = sqrt( d ); // 库函数, 求平方根 printf( “x1 = %lf, x2 = %lf”, (-b+d1)/(2*a), (-b-d1)/(2*a) ); } 运行结果:

  23. 程序11: 输入三角形的三条边的长度, 输出该三角形面积。 #include <stdio.h> #include <math.h> void main() { double a, b, c; double s, area; printf( ”Input a,b,c :” ); scanf( ”%lf%lf%lf”, &a, &b, &c ); s = a + b + c; area = sqrt( ( (s-a)+(s-b)+(s-c) ) / ( (s-a)*(s-b)*(s-c)) ); //? printf( “area = %lf”, area ); } 运行结果:

  24. 程序12: 输入二条直线, 求直线的交点。 #include <stdio.h> void main() { double a11, a12, b1; double a21, a22, b2; double x1, x2; printf( ”Input a11, a12, b1 : ” ); scanf( ”%lf%lf%lf”, &a11, &a12, &b1 ); printf( ”Input a21, a22, b2 : ” ); scanf( ”%lf%lf%lf”, &a21, &a22, &b2 ); x1 = ; // 自己填入 x2 = ; // 自己填入 printf( “x1 = %lf, x2 = %lf”, x1, x2 ); } 运行结果:

  25. 程序13: 输入一个0到90度之间的一个角度值, 输出其正弦值。 #include <stdio.h> void main() { double x; double sin_x; printf( ”Input angle x: ” ); scanf( ”%lf”, &x ); x = ( x / 360.0 ) * 2 * 3.14159265; // 角度变弧度 sin_x = x – x*x/2 + x*x*x*x/4/3/2 – x*x*x*x*x*x/6/5/4/3/2; // 想更准确? printf( “sin %d = %lf ”, x, sinx ); } 运行结果:

  26. 程序14: 输入一个0到90度之间的一个角度值, 输出其三角函数值。 #include <stdio.h> #include <math.h> // 数学函数库的头文件 void main() { double x; double sin_x; printf( ”Input angle x: ” ); scanf( ”%lf”, &x ); x = ( x / 360.0 ) * 2 * 3.14159265; // 角度变弧度 sin_x = sin(x); // 调库函数 printf( “sin %d = %lf ”, x, sin_x ); printf( “\ncos %d = %lf ”, x, cos(x) ); // 调库函数 printf( “\ncos %d = %lf ”, x, tan(x) ); // 调库函数 } 运行结果:

  27. 程序15: 一些数学库函数的调用。其它可查找数学函数表。 #include <stdio.h> #include <math.h> // 数学函数库的头文件 void main() { printf( “\n指数:%lf ”, exp( 2.302585) ); printf( “\n幂函数:%lf ”, pow( 2, 0.5 ) ); printf( “\n自然对数:%lf ”, log( 2 ) ); printf( “\n底10对数:%lf ”, log10( 2 ) ); } 运行结果:

  28. 程序16:输入半径, 输出圆的面积和周长。 #include <stdio.h> #define PI3.14159265// 符号定义语句 void main() { double r; printf( ”Input radus : ” ); scanf( ”%lf”, &r ); printf( ”%lf, %lf”, 2*PI*r, PI*r*r ); } 运行结果: 符号定义语句 #define符号名字符串 作用:编译起始时, 这一符号名 会先用后面的字符串替代。 注意:所有#开头的语句需独占一行。

  29. 程序17 问题: 求过二点的直线方程。 1. 输入: 二个点( x1, y1), ( x2, y2 ) 类型皆为 double 2. 输出: 系数a,b 使y=ax+b过上述二点; 类型皆为 double 3. 算法: x1a + b = y1 比划过程 x2a + b = y2 , 求a,b(用解二元一次方程组的方法)。 4. 代码 #inlcude <stdio.h> void main() { double x1, y1, x2, y2; // 这是存放输入的 double a, b; // 这时放结果的 scanf( ”%lf%lf%lf%lf%lf%lf”, &x1, &y1, &x2, &y2 ); a = ( y1 – y2 ) / ( x1 – x2 ); b = ( x1 * y2 – x2 * y1 ) / ( x1 – x2 ); printf( ”y=%lfx+%lf ”, a, b ); }

  30. 编程思路总结: 1. 先把外部的包装写上, 搭好框架; 2. 列出题目中已知的量和待求的量, 定好类型, 起好名字; 3. 思考需要引进哪些中间变量, 也定好类型, 起好名字; 4. 列出计算公式或算法, 必要时先画图示意; 5. 编程并运行验证。 临时量 输出量 输入量 加工 输入 输出 计算公式 算法描述 已知量 结果量 在编写任何一个程序时的思考图

  31. 输入 输出 加工 思想: 这一思想应贯穿你的每个程序设计中。 步骤: 问题分析 算法设计 程序编写 示例18 问题: 已知3点, 求圆心和半径。 不要查公式, 自己推导算法。 (以后的题目都是这样用自然语言简单描述, 自己把问题分析后具体化) 1. 输入: 三个点( x1, y1), ( x2, y2 ), ( x3, y3 ); 类型皆为 double 打草稿 2. 输出: 类型皆为 double 圆心( x0, y0 ), 半径 r ; 3. 算法: (先在草稿纸上比划) 代入3个已知点, 问题变为: ( x – x0 )2 + ( y – y0 )2 = r2, ( x1 – x0 )2 + ( y1 – y0 )2 = r2, 求 x0, y0, r ( x2 – x0 )2 + ( y2 – y0 )2 = r2, ( x3 – x0 )2 + ( y3 – y0 )2 = r2,

  32. 化简, 问题再变为: (x2-x1)x0+(y2-y1)y0 = ( x22-x12 + y22-y12 ) / 2 , 求出 x0, y0 (x3-x1)x0+(y3-y1)y0 = ( x32-x12 + y32-y12 ) / 2 , , 即2点的距离。 再得 现在问题转化为: 对一个二元一次方程的求解和求2点之间的距离。 a11, a12, a21, a22, b1, b2, 为了使算法更清晰, 引入中间变量: 类型皆为 double, 置值为: a11 = x2 - x1; a12 = y2 - y1; b1 = ( x22- x12 + y22- y12 ) / 2; a21 = x3 - x1; a22 = y3 - y1; b2 = ( x32- x12 + y32- y12 ) / 2; 则问题进一步转化为: a11x0+a12y0 = b1 , 求出 x0, y0 a21x0+a22y0 = b2 , 此时, 可解出: x0 = ( b1 * a22 – a12 * b2 ) / ( a11 * a22 - a12 * a21 ); 草稿打完 y0 = ( a11 * b2 – a21 * b1 ) / ( a11 * a22 - a12 * a21 );

  33. 程海无边, 回头是岸; break? 我们continue, 下一步就在机器上敲入程序了。 步1. 先搭框架 #inlcude <stdio.h> #include <math.h> void main() { } 注意: 要齐整! 向前看齐。

  34. 步2. 变量先定义好 (在草稿中Baidu一下) #inlcude <stdio.h> #include <math.h> void main() { double x1, y1, x2, y2, x3, y3; // 这是存放输入的 double x0, y0, r; // 这是放结果的 double a11, a12, a21, a22, b1, b2; // 这些是临时存数用的 }

  35. 步3. 加数据输入和结果输出代码 #inlcude <stdio.h> #include <math.h> void main() { double x1, y1, x2, y2, x3, y3; double x0, y0, r; double a11, a12, a21, a22, b1, b2; scanf( ”%lf%lf%lf%lf%lf%lf”, &x1, &y1, &x2, &y2, &x3, &y3 ); printf( ”(%lf,%lf), r = %lf”, x0, y0, r ); }

  36. 步4. 添加数据加工用的核心代码 (在草稿中Google一下) #inlcude <stdio.h> #include <math.h> void main() { double x1, y1, x2, y2, x3, y3; // 这是存放输入的 double x0, y0, r; // 这是放结果的 double a11, a12, a21, a22, b1, b2; // 这些是临时存数用的 scanf( ”%lf%lf%lf%lf%lf%lf”, &x1, &y1, &x2, &y2, &x3, &y3 ); a11 = x2 - x1; a12 = y2 - y1; a21 = x3 - x1; a22 = y3 - y1; b1 = ( x2*x2 - x1*x1 + y2*y2 - y1*y1 ) / 2; b2 = ( x3*x3 - x1*x1 + y3*y3 - y1*y1 ) / 2; x0 = ( b1 * a22 – a12 * b2 ) / ( a11 * a22 - a12 * a21 ); y0 = ( a11 * b2 – a21 * b1 ) / ( a11 * a22 - a12 * a21 ); r= sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 – y0 ) * ( y1 – y0 ) ); printf( ”(%lf,%lf), r = %lf”, x0, y0, r ); } 直接从代码上能看出做什么吗?

  37. 步5. 运行试试 运行结果 整半天, 就这几行代码? 要这么费劲?

  38. 示例19 问题: 求三元一次方程组的解。 1. 输入: a11,a12,a13; a21,a22,a23; a31,a32,a33; b1,b2,b3; 类型皆为 double x1, x2, x3; 2. 输出: 类型皆为 double 3. 算法: a11x1 + a12x2 + a13x3 = b1 a21x1 + a22x2 + a23x3 = b2 由 第3个式子中解出x3代入前2个式子 a31x1 + a32x2 + a33x3 = b3 (a11- a31*a13/a33)x1 + (a12-a32*a13/a33)x2 = b1-b3*a13/a33 得 (a21- a31*a23/a33)x1 + (a22-a32*a23/a33)x2 = b2-b3*a23/a33 (这是一个二元一次方程组, 我们不引入中间变量来存放系数和 右端项, 我们计算后仍将其放在a11,a12,a21,a22,b1,b2变量中) 解出 x1, x2, 并得 x3 = ( b3 - a31x1 - a32 x2 ) / a33;

  39. 4. 代码 #inlcude <stdio.h> void main() { double a11, a12, a13, a21, a22, a23, a31, a32, a33, b1, b2, b3; // 这是存放输入的 double x1, x2, x3; // 这是放结果的 scanf( ”%lf%lf%lf%lf”, &a11, &a12, &a13, &b1 ); // 第1行输入 scanf( ”%lf%lf%lf%lf”, &a21, &a22, &a23, &b2 ); // 第2行输入 scanf( ”%lf%lf%lf%lf”, &a31, &a32, &a33, &b3 ); // 第3行输入 // 临时存放 a11=(a11- a31*a13/a33);a12 = (a12-a32*a13/a33);b1 = b1-b3*a13/a33; a21=(a21- a31*a23/a33);a22 = (a22-a32*a23/a33);b2 = b2-b3*a23/a33; x1 = ( b1 * a22 – a12 * b2 ) / ( a11 * a22 - a12 * a21 ); // 这2句参考例18 x2 = ( a11 * b2 – a21 * b1 ) / ( a11 * a22 - a12 * a21 ); x3 = ( b3 - a31 * x1 - a32 * x2 ) / a33; printf( ”x1=%lf, x2=%lf, x3=%lf”, x1, x2, x3 ); } 5. 运行试验

  40. 问题: 求经过三点的一条抛物线。 示例20 1. 输入: 三个点( x1, y1), ( x2, y2 ), ( x3, y3 ); 类型皆为 double 2. 输出: a, b, c使 y = ax2 + bx + c 经过以上3点; 类型皆为 double 3. 算法: y = ax2 + bx + c; 代入3个已知点, 问题变为: x12a + x1b + c = y1 x22a + x2b + c = y2 求 a, b, c; x32a + x3b + c = y3, 这样, 可利用上例中的程序代码, 请在代码中核对。

  41. 4. 代码 #inlcude <stdio.h> void main() { double x1, y1, x2, y2, x3, y3; // 这是存放输入的 double a, b, c; // 这是放结果的 double a11, a12, a13, a21, a22, a23, a31, a32, a33, b1, b2, b3; // 这是放临时值的 scanf( ”%lf%lf%lf%lf%lf%lf”, &x1, &y1, &x2, &y2, &x3, &y3 ); // 3点输入 // 准备系数和右端项 a11 =x1 * x1; a12 = x1; a13 = 1; b1 = y1; a21 =x2 * x2; a22 = x2; a23 = 1; b2 = y2; a31 =x3 * x3; a32 = x3; a33 = 1; b3 = y3; a11=(a11- a31*a13/a33);a12 = (a12-a32*a13/a33);b1= b1-b3*a13/a33; a21=(a21- a31*a23/a33);a22 = (a22-a32*a23/a33);b2= b2-b3*a23/a33; a = ( b1 * a22 – a12 * b2 ) / ( a11 * a22 - a12 * a21 ); b = ( a11 * b2 – a21 * b1 ) / ( a11 * a22 - a12 * a21 ); c = ( b3 - a31 * a - a32 * b ) / a33; printf( ”y =%lf*x*x+%lf*x+%lf”, a, b, c ); // 结果显示 } 5. 运行试验(自己完成)

  42. 本章总结 2. 常量与变量 常量就是固定数, 整型实型要区分; 变量用于存数值, 数值也分整和实。 1. 数值 变量起名要慎重, 字母起头要牢记; 值分二类整和实, 范围精度各不同; 使用之前先定义, 之后才能存和取。 对应int与double, 区别仅在小数点。 整和实, 可转换, 默认强制由你选; 3. 运算 实转整, 丢小数, 小数指数表实数。 常量变量皆是数, 加减乘除取余数; 整数实数存内存, 内部格式大不同; 每步运算有结果, 所得结果有类型。 实数整数皆有用, 事先你得想充分。 运算顺序别忘记, 乘除加减括号先; 整数用于计个数, 数值判断全精确; 机器运算很老实, 相同运算左到右。 实数用于算数值, 超过精度会舍去。 左边变量右边数, 等号也是运算符; 算术运算表达式, 结果赋入变量中。

  43. 4. 语句 5. 程序 说明语句定类型, 赋值语句存结果; main作为主函数, 程序入口在起首; 键盘输入scanf(), 屏幕输出printf()。 变量说明前面放, 执行语句后面跟。 输入输出加处理, 编程步骤要牢记; 简单语句带分号, 分隔常常用逗号; 函数还可自定义, 输入输出更清晰。 数学函数比较多, 你想要的它都有。 草稿纸上细细画, 行行语句整整齐; 语句还有一大堆, 变量类型也较多; 条件分支与循环, 地址数组加结构。 程序运行出错误, 逐行调试极方便。

More Related