《计算机程序设计基础-c简介.ppt》由会员分享,可在线阅读,更多相关《计算机程序设计基础-c简介.ppt(71页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、1C+语言简介语言简介清华大学清华大学 郑郑 莉莉C+语言程序设计简介清华大学 郑莉2本讲内容本讲内容l类与对象类与对象l继承与派生继承与派生l多态性多态性lC+标准模板库标准模板库C+语言程序设计简介清华大学 郑莉3回顾:面向过程的设计方法回顾:面向过程的设计方法l重点重点:重点是实现的细节和过程,将数据与函数分开。l形式:形式:主模块+若干个子模块(main()+子函数)。l特点:特点:自顶向下,逐步求精功能分解。l缺点:缺点:效率低,程序的可重用性差。面向对象的思想C+语言程序设计简介清华大学 郑莉4面向对象的方法面向对象的方法l目的:目的:实现软件设计的产业化。l观点:观点:自然界是由
2、实体(对象)所组成。l程序设计方法:程序设计方法:使用面向对象的观点来描述、模仿并处理现实问题。l要求:要求:高度概括、分类、和抽象。面向对象的思想C+语言程序设计简介清华大学 郑莉5抽象抽象抽象是对具体对象(问题)进行概括,抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述抽出这一类对象的公共性质并加以描述的过程。的过程。先注意问题的本质及描述,其次是实现过程或细节。数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)。代码抽象:描述某类对象的共有的行为特征或具有的功能。抽象的实现:通过类的声明。OOP的基本特点C+语言程序设计简介清华大学 郑莉6抽象实例抽象实例钟表
3、钟表l数据抽象:数据抽象:int Hour,int Minute,int Secondl代码抽象:代码抽象:SetTime(),ShowTime()OOP的基本特点C+语言程序设计简介清华大学 郑莉7抽象实例抽象实例钟表类钟表类class Clock public:void SetTime(int NewH,int NewM,int NewS);void ShowTime();private:int Hour,Minute,Second;OOP的基本特点C+语言程序设计简介清华大学 郑莉8抽象实例抽象实例人人l数据抽象:数据抽象:char*name,char*gender,int age,in
4、t idl代码抽象:代码抽象:生物属性角度:GetCloth(),Eat(),Step(),社会属性角度:Work(),Promote(),OOP的基本特点C+语言程序设计简介清华大学 郑莉9封装封装将抽象出的数据成员、代码成员相结将抽象出的数据成员、代码成员相结合,将它们视为一个整体。合,将它们视为一个整体。目的是曾强安全性和简化编程,使用者不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。实现封装:类声明中的OOP的基本特点C+语言程序设计简介清华大学 郑莉10封装封装l实例:实例:class Clock public:void SetTime(int New
5、H,int NewM,int NewS);void ShowTime();private:int Hour,Minute,Second;边界特定的访问权限OOP的基本特点外部接口C+语言程序设计简介清华大学 郑莉11继承与派生继承与派生是是C+中支持层次分类的一种机制,中支持层次分类的一种机制,允许程序员在保持原有类特性的基础上,允许程序员在保持原有类特性的基础上,进行更具体的说明。进行更具体的说明。实现:声明派生类实现:声明派生类OOP的基本特点C+语言程序设计简介清华大学 郑莉12多态性多态性l多态:同一名称,不同的功能实现方式。多态:同一名称,不同的功能实现方式。l目的:达到行为标识统一
6、,减少程序中标目的:达到行为标识统一,减少程序中标识符的个数。识符的个数。l实现:重载函数和虚函数实现:重载函数和虚函数OOP的基本特点C+语言程序设计简介清华大学 郑莉13c+中的类中的类l类是具有相同属性和行为的一组对象类是具有相同属性和行为的一组对象的集合,它为属于该类的全部对象提的集合,它为属于该类的全部对象提供了统一的抽象描述,其内部包括属供了统一的抽象描述,其内部包括属性和行为两个主要部分。性和行为两个主要部分。l利用类可以实现数据的封装、隐藏、利用类可以实现数据的封装、隐藏、继承与派生。继承与派生。l利用类易于编写大型复杂程序,其模利用类易于编写大型复杂程序,其模块化程度比块化程
7、度比C中采用函数更高。中采用函数更高。类 和 对 象C+语言程序设计简介清华大学 郑莉14类的声明形式类的声明形式类是一种用户自定义类型,其声明形式:类是一种用户自定义类型,其声明形式:class 类名称 public:公有成员(外部接口)private:私有成员 protected:保护型成员类 和 对 象C+语言程序设计简介清华大学 郑莉15公有类型成员公有类型成员是类与外部的接口,任何外部函数都是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。可以访问公有类型数据和函数。以关键字以关键字publicpublic修饰。修饰。类 和 对 象C+语言程序设计简介清华大学 郑莉16私有
8、类型成员私有类型成员只允许本类中的函数访问,而类外部只允许本类中的函数访问,而类外部的任何函数都不能访问。的任何函数都不能访问。以关键字以关键字privateprivate修饰。修饰。如果如果紧跟在类名称的后面声明私有成员,紧跟在类名称的后面声明私有成员,则则关键字关键字privateprivate可以可以省略。省略。类 和 对 象C+语言程序设计简介清华大学 郑莉17保护类型保护类型与与private类似,其差别表现在继承与类似,其差别表现在继承与派生时对派生类的影响不同。派生时对派生类的影响不同。以关键字以关键字protectedprotected修饰。修饰。类 和 对 象C+语言程序设计
9、简介清华大学 郑莉18类的成员类的成员class Clock public:void SetTime(int NewH,int NewM,int NewS);void ShowTime();private:int Hour,Minute,Second;类 和 对 象数据成员函数成员void Clock:SetTime(int NewH,int NewM,int NewS)Hour=NewH;Minute=NewM;Second=NewS;void Clock:ShowTime()coutHour:Minute:Second;19C+语言程序设计简介清华大学 郑莉20数据成员数据成员l与一般的变
10、量声明相同,但需要将它与一般的变量声明相同,但需要将它放在类的声明体中。放在类的声明体中。类 和 对 象C+语言程序设计简介清华大学 郑莉21函数成员函数成员l在类中说明原型,可以在类外给出函数在类中说明原型,可以在类外给出函数体实现,并在函数名前使用类名加以限体实现,并在函数名前使用类名加以限定。也可以直接在类中给出函数体,形定。也可以直接在类中给出函数体,形成内联成员函数。成内联成员函数。l允许声明重载函数和带默认形参值的函允许声明重载函数和带默认形参值的函数。数。类 和 对 象C+语言程序设计简介清华大学 郑莉22对象对象l类的对象是该类的某一特定实体,即类的对象是该类的某一特定实体,即
11、类类型的变量。类类型的变量。l声明形式:声明形式:类名类名 对象名对象名;l例:例:Clock myClock;类 和 对 象C+语言程序设计简介清华大学 郑莉23类中成员的访问方式类中成员的访问方式l类中成员互访类中成员互访直接使用成员名l从类外访问从类外访问使用“对象名.成员名”方式访问 public 属性的成员类 和 对 象C+语言程序设计简介清华大学 郑莉24类的应用举例类的应用举例#includeusing namespace std;class Clock ./类的声明略类的声明略/.类的实现略类的实现略int main()Clock myClock;myClock.SetTime
12、(8,30,30);myClock.ShowTime();类 和 对 象C+语言程序设计简介清华大学 郑莉25组合的概念组合的概念l可以在已有的抽象的基础上实现更复可以在已有的抽象的基础上实现更复杂的抽象。杂的抽象。l类中的数据成员是另一个类的对象。类中的数据成员是另一个类的对象。类 的 组 合C+语言程序设计简介清华大学 郑莉26举例举例class Point private:float x,y;/点的坐标 public:Point(float h,float v);/构造函数 float GetX(void);/取X坐标 float GetY(void);/取Y坐标 void Draw(v
13、oid);/在(x,y)处画点;/.函数的实现略类 的 组 合class Line private:Point p1,p2;/线段的两个端点线段的两个端点 public:Line(Point a,Point b);/构造函数构造函数 Void Draw(void);/画出线段画出线段;/.函数的实现略函数的实现略4928继承与派生简介继承与派生简介C+语言程序设计简介清华大学 郑莉29类的继承与派生类的继承与派生l保持已有类的特性而构造新类的过程保持已有类的特性而构造新类的过程称为继承。称为继承。l在已有类的基础上新增自己的特性而在已有类的基础上新增自己的特性而产生新类的过程称为派生。产生新类
14、的过程称为派生。l被继承的已有类称为基类(或父类)。被继承的已有类称为基类(或父类)。l派生出的新类称为派生类。派生出的新类称为派生类。C+语言程序设计简介清华大学 郑莉30继承与派生问题举例继承与派生问题举例类的继承与派生C+语言程序设计简介清华大学 郑莉31继承与派生问题举例继承与派生问题举例类的继承与派生C+语言程序设计简介清华大学 郑莉32继承与派生问题举例继承与派生问题举例类的继承与派生C+语言程序设计简介清华大学 郑莉33继承与派生问题举例继承与派生问题举例类的继承与派生C+语言程序设计简介清华大学 郑莉34继承与派生的目的继承与派生的目的l继承的目的:实现代码重用。继承的目的:实
15、现代码重用。l派生的目的:当新的问题出现,原有派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,程序无法解决(或不能完全解决)时,需要对原有程序进行改造。需要对原有程序进行改造。类的继承与派生C+语言程序设计简介清华大学 郑莉35派生类的声明派生类的声明class 派生类名:派生类名:继承方式继承方式 基类名基类名 成员声明;成员声明;类的继承与派生C+语言程序设计简介清华大学 郑莉36继承举例继承举例class Point/基类基类Point类的声明类的声明public:/公有函数成员公有函数成员void InitP(float xx=0,float yy=0)X=xx;Y=
16、yy;void Move(float xOff,float yOff)X+=xOff;Y+=yOff;float GetX()return X;float GetY()return Y;private:/私有数据成员私有数据成员float X,Y;类成员的访问控制class Rectangle:public Point /派生类声明派生类声明public:/新增公有函数成员新增公有函数成员void InitR(float x,float y,float w,float h)InitP(x,y);W=w;H=h;/调用基类公有成员函数调用基类公有成员函数float GetH()return H;
17、float GetW()return W;private:/新增私有数据成员新增私有数据成员float W,H;37#include#includeusing namecpace std;int main()Rectangle rect;rect.InitR(2,3,20,10);/通过派生类对象访问基类公有成员通过派生类对象访问基类公有成员rect.Move(3,2);coutrect.GetX(),rect.GetY(),rect.GetH(),rect.GetW()endl;return 0;3839多态性简介多态性简介C+语言程序设计简介清华大学 郑莉40多态性的概念多态性的概念l多态
18、性是面向对象程序设计的重要特多态性是面向对象程序设计的重要特征之一。征之一。l多态性是指发出同样的消息被不同类多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同型的对象接收时有可能导致完全不同的行为。的行为。l多态的实现:多态的实现:函数重载运算符重载虚函数C+语言程序设计简介清华大学 郑莉41问题举例问题举例复数的运算复数的运算class complex/复数类声明复数类声明public:complex(double r=0.0,double i=0.0)/构造函数构造函数 real=r;imag=i;void display();/显示复数的值显示复数的值private:do
19、uble real;double imag;运算符重载C+语言程序设计简介清华大学 郑莉42问题举例问题举例复数的运算复数的运算l用用“+”、“-”能够实现复数的加减运能够实现复数的加减运算吗?算吗?l实现复数加减运算的方法实现复数加减运算的方法 重载重载“+”、“-”运算符运算符运算符重载C+语言程序设计简介清华大学 郑莉43运算符重载的实质运算符重载的实质l运算符重载是对已有的运算符赋予多重含义运算符重载是对已有的运算符赋予多重含义l必要性必要性C+中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)l实现机制实现机制将指定的运算表达式转化为对运算符函数的调用,运
20、算对象转化为运算符函数的实参。编译系统对重载运算符的选择,遵循函数重载的选择原则。运算符重载C+语言程序设计简介清华大学 郑莉44运算符重载 例例 将将“+”+”、“-”-”运算重载为复数类运算重载为复数类的成员函数。的成员函数。l 规则规则:实部和虚部分别相加减。实部和虚部分别相加减。l 操作数操作数:两个操作数都是复数类的对象。两个操作数都是复数类的对象。#includeusing namespace std;class complex/复数类声明复数类声明public:/外部接口外部接口complex(double r=0.0,double i=0.0)real=r;imag=i;/构造
21、函数构造函数complex operator+(complex c2);/+重载为成员函数重载为成员函数complex operator-(complex c2);/-重载为成员函数重载为成员函数void display();/输出复数输出复数private:/私有数据成员私有数据成员double real;/复数实部复数实部double imag;/复数虚部复数虚部;45complex complex:operator+(complex c2)/重载函数实现重载函数实现complex c;c.real=c2.real+real;c.imag=c2.imag+imag;return compl
22、ex(c.real,c.imag);46complex complex:operator-(complex c2)/重载函数实现重载函数实现complex c;c.real=real-c2.real;c.imag=imag-c2.imag;return complex(c.real,c.imag);47void complex:display()cout(real,imag)endl;int main()/主函数主函数 complex c1(5,4),c2(2,10),c3;/声明复数类的对象声明复数类的对象coutc1=;c1.display();coutc2=;c2.display();c
23、3=c1-c2;/使用重载运算符完成复数减法使用重载运算符完成复数减法coutc3=c1-c2=;c3.display();c3=c1+c2;/使用重载运算符完成复数加法使用重载运算符完成复数加法coutc3=c1+c2=;c3.display();48程序输出的结果为:程序输出的结果为:c1=(5,4)c2=(2,10)c3=c1-c2=(3,-6)c3=c1+c2=(7,14)49C+语言程序设计简介清华大学 郑莉50虚函数虚函数l虚函数是动态绑定的基础。虚函数是动态绑定的基础。l是非静态的成员函数。是非静态的成员函数。l在类的声明中,在函数原型之前写在类的声明中,在函数原型之前写virt
24、ual。lvirtual 只用来说明类声明中的原型,不能用在只用来说明类声明中的原型,不能用在函数实现时。函数实现时。l具有继承性,基类中声明了虚函数,派生类中具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。无论是否说明,同原型函数都自动为虚函数。l本质:不是重载声明而是覆盖。本质:不是重载声明而是覆盖。l调用方式:通过基类指针或引用,执行时会调用方式:通过基类指针或引用,执行时会根据根据指针指向的对象的类指针指向的对象的类,决定调用哪个函数。,决定调用哪个函数。虚 函 数C+语言程序设计简介清华大学 郑莉51例例#include using namespace
25、 std;class B0/基类基类B0声明声明public:/外部接口外部接口virtual void display()/虚成员函数虚成员函数 coutB0:display()endl;class B1:public B0/公有派生公有派生 public:void display()coutB1:display()endl;class D1:public B1/公有派生公有派生 public:void display()coutD1:display()display();int main()/主函数主函数 B0 b0,*p;/声明基类对象和指针声明基类对象和指针B1 b1;/声明派生类对象
26、声明派生类对象D1 d1;/声明派生类对象声明派生类对象p=&b0;fun(p);/调用基类调用基类B0函数成员函数成员p=&b1;fun(p);/调用派生类调用派生类B1函数成员函数成员p=&d1;fun(p);/调用派生类调用派生类D1函数成员函数成员运行结果:运行结果:B0:display()B1:display()D1:display()52C+语言程序设计简介清华大学 郑莉53函数模板函数模板l函数模板可以用来创建一个通用功能函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。步简化重载函数的函数体设计。l声明方
27、法:声明方法:template 函数声明 函 数 模 板C+语言程序设计简介清华大学 郑莉54求绝对值函数的模板求绝对值函数的模板#include#includeusing namespace std;using namespace std;templatetypename template T T abs(abs(T T x)x)return x0?-x:x;return x0?-x:x;int main()int main()int n=-5;int n=-5;double d=-5.5;double d=-5.5;coutabs(coutabs(n n)endl;)endl;coutab
28、s(coutabs(d d)endl;)endl;函 数 模 板运行结果:55.5C+语言程序设计简介清华大学 郑莉55求绝对值函数的模板分析求绝对值函数的模板分析l编译器从调用编译器从调用abs()时实参的类型,推时实参的类型,推导出函数模板的类型参数。例如,对导出函数模板的类型参数。例如,对于调用表达式于调用表达式abs(n),由于实参,由于实参n为为int型,所以推导出模板中类型参数型,所以推导出模板中类型参数T为为int。l当类型参数的含义确定后,编译器将当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数:以函数模板为样板,生成一个函数:int abs(int x)retu
29、rn x0?-x:x;函 数 模 板C+语言程序设计简介清华大学 郑莉56类模板的作用类模板的作用使用类模板使用户可以为类声明一使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本的返回值,能取任意类型(包括基本类型的和用户自定义类型)。类型的和用户自定义类型)。类 模 板C+语言程序设计简介清华大学 郑莉57类模板的声明类模板的声明l类模板:类模板:template class 类名类成员声明l如果需要在类模板以外定义其成员如果需要在类模板以外定义其成员函
30、数,则要采用以下的形式:函数,则要采用以下的形式:template 类型名 类名:函数名(参数表)类 模 板58C+标准模板库简介标准模板库简介C+语言程序设计简介清华大学 郑莉59泛型程序设计泛型程序设计l将程序写得尽可能通用将程序写得尽可能通用 l将算法从特定的数据结构中抽象出来,成将算法从特定的数据结构中抽象出来,成为通用的为通用的lC+的模板为泛型程序设计奠定了关键的基的模板为泛型程序设计奠定了关键的基础础 lSTL是泛型程序设计的一个范例是泛型程序设计的一个范例 容器(container)迭代器(iterator)算法(algorithms)函数对象(function object)
31、C+语言程序设计简介清华大学 郑莉60容器容器l容器类是容纳、包含一组元素或元素容器类是容纳、包含一组元素或元素集合的对象。集合的对象。l异类容器类与同类容器类异类容器类与同类容器类l顺序容器与关联容器顺序容器与关联容器l七种基本容器:七种基本容器:向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)概念和术语C+语言程序设计简介清华大学 郑莉61容器的接口容器的接口l通用容器运算符通用容器运算符=,!=,=,=,=l方法(函数)方法(函数)迭代方法lbegin(),end(),rbegin(
32、),rend()访问方法lsize(),max_size(),swap(),empty()C+语言程序设计简介清华大学 郑莉62迭代器迭代器l迭代器是面向对象版本的指针迭代器是面向对象版本的指针指针可以指向内存中的一个地址迭代器可以指向容器中的一个位置lSTL的每一个容器类模版中,都定义的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。元素,而无需关心元素的具体类型。概念和术语C+语言程序设计简介清华大学 郑莉63算法算法lC+标准模板库中包括标准模板库
33、中包括70多个算法多个算法其中包括查找算法,排序算法,消除算法,记数算法,比较算法,变换算法,置换算法和容器管理等等。l这些算法的一个最重要的特性就是它这些算法的一个最重要的特性就是它们的统一性,并且可以广泛用于不同们的统一性,并且可以广泛用于不同的对象和内置的数据类型。的对象和内置的数据类型。概念和术语C+语言程序设计简介清华大学 郑莉64顺序容器顺序容器l顺序容器的接口顺序容器的接口插入方法lpush_front(),push_back(),insert(),运算符“=”删除方法lpop(),erase(),clear()迭代访问方法l使用迭代器其它顺序容器访问方法(不修改访问方法)lfr
34、ont(),back(),下标运算符容 器C+语言程序设计简介清华大学 郑莉65顺序容器顺序容器向量向量l向量属于顺序容器,用于容纳不定长向量属于顺序容器,用于容纳不定长线性序列(即线性群体),提供对序线性序列(即线性群体),提供对序列的快速随机访问(也称直接访问)列的快速随机访问(也称直接访问)l向量是动态结构,它的大小不固定,向量是动态结构,它的大小不固定,可以在程序运行时增加或减少。可以在程序运行时增加或减少。l例例10-1求范围2N中的质数,N在程序运行时由键盘输入。容 器#include#include#include#include#include#include/包含向量容器头文
35、件包含向量容器头文件using namespace std;using namespace std;int main()int main()vector A(10);vector A(10);int n;int n;int primecount=0,i,j;int primecount=0,i,j;cout=2 as upper limit:;cout=2 as upper limit:;cin n;cin n;Aprimecount+=2;Aprimecount+=2;66 for(i=3;i n;i+)for(i=3;i n;i+)if(primecount=A.size()if(prim
36、ecount=A.size()A.resize(primecount+10);A.resize(primecount+10);if(i%2=0)if(i%2=0)continue;continue;j=3;j=3;while(j=i/2&i%j!=0)while(j i/2)Aprimecount+=i;if(j i/2)Aprimecount+=i;for(i=0;iprimecount;i+)/for(i=0;iprimecount;i+)/输出质数输出质数 coutsetw(5)Ai;coutsetw(5)Ai;if(i+1)%10=0)/if(i+1)%10=0)/每输出每输出1010
37、个数换行一次个数换行一次 cout endl;cout endl;coutendl;coutendl;67C+语言程序设计简介清华大学 郑莉68顺序容器顺序容器列表列表l列表主要用于存放双向链表,可以从任意列表主要用于存放双向链表,可以从任意一端开始遍历。列表还提供了拼接一端开始遍历。列表还提供了拼接(splicing)操作,将一个序列中的元素从)操作,将一个序列中的元素从插入到另一个序列中。插入到另一个序列中。l例例从键盘输入10个整数,用这些整数值作为结点数据,生成一个链表,按顺序输出链表中结点的数值。然后从键盘输入一个待查找整数,在链表中查找该整数,若找到则删除该整数所在的结点(如果出现
38、多次,全部删除),然后输出删除结点以后的链表。在程序结束之前清空链表。容 器#include#include#include#include using namespace std;using namespace std;int main()int main()list Link;list Link;/构造一个列表用于存放整数链表构造一个列表用于存放整数链表 int i,key,item;int i,key,item;for(i=0;i 10;i+)/for(i=0;i item;cinitem;Link.push_front(item);Link.push_front(item);coutL
39、ist:;/coutList:;/输出链表输出链表69 list:iterator p=Link.begin();list:iterator p=Link.begin();while(p!=Link.end()/while(p!=Link.end()/输出各节点数据,直到链表尾输出各节点数据,直到链表尾 cout*p ;cout*p ;p+;/p+;/使使P P指向下一个节点指向下一个节点 cout endl;cout endl;cout cout key;cin key;Link.remove(key);Link.remove(key);cout List:;/cout List:;/输出链
40、表输出链表 p=Link.begin();p=Link.begin();/使使P P重新指向表头重新指向表头 while(p!=Link.end()while(p!=Link.end()cout*p ;cout*p ;p+;/p+;/使使P P指向下一个节点指向下一个节点 cout endl;cout endl;70C+语言程序设计简介清华大学 郑莉71标准标准C+库中的算法库中的算法l算法本身是一种函数模板算法本身是一种函数模板l不可变序列算法不可变序列算法(Non-mutating algorithmsNon-mutating algorithms)不直接修改所操作的容器内容的算法l可变序列算法可变序列算法(Mutating algorithmsMutating algorithms)可以修改它们所操作的容器的元素。l排序相关算法排序相关算法l数值算法数值算法算 法