精华内容
下载资源
问答
  • 曾获“汉滨区教学能手”,“汉滨区优秀教师”,“高新区优秀教师”,“高新区教育先进个人”, “高新区优秀班主任”,“优秀备课组长”等荣誉称号 [摘要]:因式分解贯穿整个数学学科,一元二次多项式的...
    94b990f517d6509f022b14a50e1ec62a.gifb5bf328e7d0e6b5aaba795e0fc561850.png作者简介:尹锋,一级教师,从教11年,参与6轮高三备考,培养近千余人学生考上本科大学,2018年培养了从教生涯来首个清华大学生。主持区级课题一项,参与区级课题一项,发表教育教学论文2篇。曾获“汉滨区教学能手”,“汉滨区优秀教师”,“高新区优秀教师”,“高新区教育先进个人”, “高新区优秀班主任”,“优秀备课组长”等荣誉称号       

    [摘要]因式分解贯穿整个数学学科,一元二次多项式的因式分解的应用更是无处不在。本文将给出高等数学中因式分解思想在初等数学中的一个应用。给出整系数一元二次多项式因式分解判定定理:整系数多项式32b15120a946d931b39d0feb881fbd35.png可分解为两个整系数一次多项式之积的充要条件是:842dbe6f7b3353075741ce4616fb58ad.png为完全平方数。并将定理推广至有理系数范围。                     

    [关键词]:有理系数、整系数、一元二次多项式、因式分解、因式分解的判定。                    

    首先引入几个概念:

    多项式n是一个非负整数,形式表达式  91f8d94d060d8d18a71b96ac2bd4f77a.png,其中0915362ca2ab5fa410e5771a871c2d9a.png称为数域aa3ff86a31d8bcf361e49728d9fdf293.png上的一元多项式。

    因式分解:将数域P上的多项式分解为数域P上的若干个不可约 多项式的乘积的分解方式称多项式的因式分解。

    八年级我们初识因式分解,从此因式分解就和我们的数学学习分不开了,尤其是在整个中学阶段要学习的代数式化简、一元二次方程的根,一元二次函数等模块的应用。

    我们知道有些多项式容易分解,有些多项式难分解,还有些多项式不能分解,并且很多时候因式分解的应用都在有理系数上讨论。既然要分解因式,首先得判断所给的多项式能不能因式分解,如果不能,显然就不用分解了,也就没必要费大力气去寻找分解方法了。那问题出来了,在初等数学中如何判定一个多项式能否因式分解呢?

    纵观初等数学中有关因式分解的方法:

    1、基本公式法(包括十字相乘法)

    2、待定系数法

    3、利用多项式对应方程的根来分解因式

    基本公式法(包括十字相乘法)具有很大局限性,仅能判定少数具有基本公式型的多项式的因式分解情况;虽然待定系数法几乎能够判定所有的多项式能否因式分解,但运算能力的要求是相当高的,学生能力达不到,老师也不提倡;利用多项式的根分解,是一个较实用的方法,那得先求根,如果求根再需要用到因式分解,那又该怎么办呢?

    寻求一个初等的能够快速的判定一个多项式能否因式分解的方法,还是很有意义的。本文将带领读者共同来寻找有理数域上一个有理系数一元二次多项式的因式分解的判定方法,思路分两步分析:

    一、从高等数学的角度分析:

    高等数学中有关因式分解的定理:

    有理根判定定理[1]: 

    91f8d94d060d8d18a71b96ac2bd4f77a.png是一个整系数多项式,如果s/t是它的一个有理根,其中互素,那么必有0b37c8602b772b597ca2aed6248a14a0.png。特别地,如果多项式的首项系数那么多项式的有理根都是整根,而且是的因子。

    Eisenstein判别法[1]:

    91f8d94d060d8d18a71b96ac2bd4f77a.png是一个整系数多项式,如果存在一个素数p,使得:

    705971280d855fdd7b33c67408ff74eb.png

         那么多项式在有理数域上不可约。

    从上面两个定理可以看出,要判断一个整系数多项式是否能分解为几个整系数一次多项式的积可转化为判定该多项式在有理数域上是否可约或是否有有理根进行判定。

    二、从初等数学角度分析[3]:

    在学习了一元二次方程后,我们知道一个一元二次多项式在实数范围能够因式分解的充要条件:一元二次多项式对应的一元二次方程有实根。

    无论从高等数学角度分析还是从初等数学角度分析,利用多项式的根作为因式分解判定依据的方法都是最基本的判定方法。既然根能判断一个多项式能否因式分解,那我们就从一元二次方程的根出发顺藤摸瓜,找到种瓜人,找出我们要寻找的判定方法。

    一元二次方程aaed86a19e882ae2ec832deb47f857b2.png有实根的充要条件是:842dbe6f7b3353075741ce4616fb58ad.png并且其根具有形式:80decb8f1cc95e92dc8c5aea77a5a2d8.png。这说明有理系数多项式:46844018d8530177133fdb3f318fcf3f.png在有理系数域上能否因式分解等价于整系数一元二次方程aaed86a19e882ae2ec832deb47f857b2.png是否有有理根。若有理系数一元二次方程aaed86a19e882ae2ec832deb47f857b2.png有有理根,则从根的形式知:029724630da537a7b27ae2a128bd5c87.png为有理数,即:842dbe6f7b3353075741ce4616fb58ad.png为完全平方数。我们要寻找的判别方法到此基本上水落石出了。

    下面将给出整系数一元二次多项式在整数范围内因式分解的一个判定定理。

    定理:整系数多项式32b15120a946d931b39d0feb881fbd35.png可分解为两个整系数一次多项式之积的充要条件是:842dbe6f7b3353075741ce4616fb58ad.png为完全平方数。在证明定理前先证明以下引理:引理Ⅰ[2]20a54c3497bcad8fc6f7496f39312c53.png,若4cecf58daad0d5ed61ffd8739d263c66.png,则存在这样一种分解方式0b65776df951ef436fe4b34b5b1408d8.png使得3283a1297e84822a17f1b5db48b33ea1.png

     证明:对099ea60e00ee2cbf0985168868fece90.png作如下分解:

      6ea8ecb38f3994bac67f03457557d3ee.png  其中ec32dbad01f06a47ffa44de1642163a8.png为1或素数。   d9af339ede5af1ff1fdc8274a1b6f0ee.png   b0f87cae0800038c3faf63340a264d56.png  记c69366b4ecac7f3663f82754db48cf6d.png  则:050197d70d1c81327f6b61b877b0dc02.png1fe1128ac33ce824425e3efbcd807a6c.png  即存在a28f66207c0e51b82d3b4f2369a77a97.png  使得:d100bb7e1a2f6a33b783e6645057405c.png  取8a0c8f33782723a2e8197dee2b1a31d6.png4e4f795fc3af05e46d3a6ad5dcc55879.png  显然410ebfa3957f3095706a3dd71525badd.png此时7cc2a899b10a15be9fac2486d488c61b.pngecfebb49273a824176efdcd49e29112b.png引理Ⅱ[2]:方cec0719fc2e8f4e12387fb7712c5029c.png有整数解e533c5bb99c3388c65be9ae1134ae2a7.png的充要条件:b,d同奇偶。证明:7fc3acfa8676898cd5ceb9406ffca781.png同奇偶5717916184d7548e3d78c10f0adebfb4.png

     记bb9202fa8facc3cf2d52be57c057e735.pngd3fdeded7a61134f019e35b9640beee7.png

    由方程99708f8ed08779f73329fa8f22dfa01f.png必有整数解9f18abc7d1e9d19cdc8116a2860d5f78.png有整数解。

    下证定理:

         证:先证必要性:afaefb0c096e433e63c5558f0c98963a.png能分解为两个整系数一次多项式的积,则46844018d8530177133fdb3f318fcf3f.png必可分解为如下形式:     4d07e689a39304a36db7617a40809368.png  即13406f8ed0cc7712034c7fb92bd34044.png    1896143e3dd99c0221390d2eb8ae5bc2.png  即842dbe6f7b3353075741ce4616fb58ad.png为完全平方数。   再证充分性:842dbe6f7b3353075741ce4616fb58ad.png为完全平方数,不妨设113424c78709b91a9ff53f4646a200b8.png从而:5a4aa69c208ced23a3aad94affdb3a15.png由引理知:存在这样一种分解方式          4a8c1ce9237a6c913c164ff6fac6bfb3.png    使得ba4d28b7dccfcb93842a43ce1209cc34.png 即有145003da9dc85c3223607b904941ec05.png 将代入多项式得:  d29de4d9f025ef69af19169f4d60e96e.png多项式可分解为两个整系数一次多项式之积。综上定理证毕。

    定理的推广:有理系数多项式32b15120a946d931b39d0feb881fbd35.png可分解为两个有理系数一次多项式之积的充要条件是:842dbe6f7b3353075741ce4616fb58ad.png为有理数的完全平方数。

    推论Ⅰ同为奇数时,46844018d8530177133fdb3f318fcf3f.png在有理数域上不可因式分解。

    推论:记的最大公约数1ae3acf05439bb0eea7d9a8a4c3d6f64.png,若0beb80189fc10f8e151b5968ec5bb9c8.png,则:46844018d8530177133fdb3f318fcf3f.png可分解3baff920784a500f413990179ec1b4e4.png的形式,其中f403c5913b235529884ef8035c91f893.png

    定理的推广及推论的证明可由引理及定理直接得出,详细过程在此不再赘述。

     [参考文献]:

    [1]王萼芳、石生明:高等代数(2003.7第3版,高等教育出版社)

    [2]潘承洞、潘承彪:初等数论(2006.9,北京大学出版社)

    [3]人民教育出版社中学数学课程教材研究开发中心:八年级数学教材(2007.6 ,人民教育出版社)

    a2084de45a9f5ffc057e7b5e4d9e0603.png                                          1d5fd47745ad87120bc4bc3a373f0d14.gif

    听说转发文章

    会给你带来好运

    展开全文
  • 考虑到《二元齐对称多项式与二项式定理》的总结与提高,在全书的最后安排了第九章,简单介绍了个代数系统——线性空间。线性空间的基本概念,在科技领域内已可以算得上是常识性的内容(概念)了,熟悉这重要而又...
  •  好吧,这一次基本上完全是在面向过程编程,没有看出来任何的面向对象的特性。  复杂度:  可以看到模块间的相互耦合度很高,PolyDerive方法的非结构化程度也不够理想,是非常不合格的面向对象程序。 2.正则...

      第一次作业分析

    1.程序结构分析

      类图:

      好吧,这一次基本上完全是在面向过程编程,没有看出来任何的面向对象的特性。

      复杂度:

      可以看到模块间的相互耦合度很高,PolyDerive方法的非结构化程度也不够理想,是非常不合格的面向对象程序。

    2.正则表达式

      从带符号整数到项到多项式一步步地写出对应的正则表达式:

        符号    String signStrPat = "(?:\\+|-)";
        带符号整数   String intStrPat = "(?:\\+|-)?\\d+";
               String termStrPat = "(?:(?:(?:(?:(?:\\+|-)?\\d+\\s*\\*)|\\+|-)?"
                + "\\s*x\\s*(?:\\^\\s*(?:\\+|-)?\\d+)?)|(?:(?:\\+|-)?\\d+))";
        多项式     String polyStrPat = "^\\s*" + signStrPat + "?\\s*" + termStrPat 
                + "(?:\\s*" + signStrPat + "\\s*" + termStrPat + "\\s*)*+$";

    3.总结

       虽然程序没有bug,但是第一次作业只能说是java编程,不能叫面向对象程序设计,写的很烂,不过熟悉了java基本语法和java正则表达式。

      第二次作业分析

    1.程序结构分析

       类图:

      这一次采用了面向对象的思想,定义了因子、项和多项式类,但是不够熟练,在架构上存在不小的问题:

      BigInt类其实完全没有必要,Index类和Term类功能严重重叠,求导操作全部集中在PolyDerive等等等等。

      这些都是在架构上很丑陋的一些设计,也导致了无法进行三角函数的化简,以及下一次作业需要再次重构。

     

      复杂度:

      部分模块的耦合度还是比较高,勉强合格吧。

    2.正则表达式

      同样采用层次化的写法,而且将每一个类对应的正则表达式用public static final修饰写在了每个类的内部

        带符号整数  public static final String INTPAT = "(?:\\+|-)?\\d+";

        因子       public static final String FACPAT = "(?:(?:(?:x|(?:(?:sin|cos)\\s*\\(\\s*x\\s*\\)))"

                + "(?:\\s*\\^\\s*" + BigInt.INTPAT + ")?)|" + BigInt.INTPAT + ")";

                public static final String TERMPAT = "(?:(?:\\+|-)?\\s*" + Factor.FACPAT

                + "(?:\\s*\\*\\s*" + Factor.FACPAT + ")*+)";

        多项式      public static final String POLYPAT = "(?:\\+|-)?\\s*" + Term.TERMPAT

                + "(\\s*[\\+-]\\s*" + Term.TERMPAT + ")*+";

    3.总结

       没有bug,但是依旧丑陋。

      第三次作业分析

    1.程序结构分析

       类图:

      这次作业的因子有常数、幂函数、三角函数、表达式因子,我的思路就是构造这些因子的类继承总的因子类,并且构造项和表达式类,然后用递归下降分析法处理输入,构造相应的对象。  

      化简(simplify方法)时调用类内similar方法和equals方法进行判断。

      复杂度:

      由于sin和cos三角函数因子内部有因子,所以耦合度过高。另外,similar方法和重写的equals方法因为要遍历比较所以复杂度过高。这也导致了公测时三个样例运行时间过长。

    2.输入处理

      由于引入了表达式因子,所以没有想出来怎么用java正则表达式来对整体表达式进行识别。

      但是联系到编译原理课上学过的词法分析和语法分析,可以很自然地用自动机和递归下降分析法来处理输入。

      但是这种写法最终导致程序的复杂度很高,而且遇到深层次的括号嵌套时会构造很多冗余的、没有必要的对象(例如"((((x))))",会调用五次表达式分析,构造五个表达式、项、因子)。

    3.总结

      这次作业公测出现了三个测试样例运行时间过长而判错,由于自己测试时未进行多重括号嵌套的测试,事先没有发现这个问题。

      收获与反思

      经过这三次作业已经基本理解了面向对象的思想,但是在一些细节上还不够熟练,需要多加雕琢。

      在架构上一定要多花心思,在测试上一定要下功夫。

    转载于:https://www.cnblogs.com/Raze11he/p/10609915.html

    展开全文
  • 多项式链表

    2016-03-12 21:23:49
    数据结构与算法分析——c语言描述 ...这里完全是来个二循环排序,应该有更好的办法,而且排序嫌麻烦直接交换内容而不是用了链表的交换。以后会更新代码的。 list.h typedef struct { int Coefficient; int Expone

    数据结构与算法分析——c语言描述 第三章的多项式链表


    2016-3-12

    用c来写类好酸爽。。。。

    有几个地方还没完成,一个是初始化,而是输入输出,三是书中要求以次数递减的顺序排序。这里完全是来个二次循环排序,应该有更好的办法,而且排序嫌麻烦直接交换内容而不是用了链表的交换。还有就是乘完以后没有合并同类项。。。。以后会更新代码的。


    2016-3-18

    刚好数据结构老师也布置了这个作业,顺便完成,什么都搞定了。可以初始化,输入输出,递减顺序排序不再是二次循环排序了。


    几点心得:

    功能与功能之间分清楚,类与类之间分清楚,封装起来,模块化,底层细节隐藏。虽然不是c++,其实也是用c来写类,思想都一样。

    链表归链表,多项式是基于链表,用的是链表的表层函数,那就不要再管链表了。

    输入的时候每输入一个根据合适的位置插入

    做加法的时候因为两个都是排好序的,所以不需要每次都根据合适的位置插入,直接选最大的插入就行,然后下一个

    乘法、输入都调用了插入函数。

    vs2015通过编译,测试无bug,如果有问题请留言谢谢


    list.h

    typedef struct {
    	int Coefficient;//系数
    	int Exponent;//指数
    }ElementType;
    
    
    #ifndef _List_H  
    #define _List_H  
    
    struct Node;
    typedef struct Node *PtrToNode;
    typedef PtrToNode List;
    typedef PtrToNode Position;
    
    List CreatList();
    List MakeEmpty(List L);
    int IsEmpty(List L);
    int IsLast(Position P, List L);
    Position Find(ElementType X, List L);
    void Delete(ElementType X, List L);
    Position FindPrevious(ElementType X, List L);
    void Insert(ElementType X, Position P);
    void DeleteList(List L);
    Position Header(List L);
    Position First(List L);
    Position Advance(Position P);
    ElementType Retrieve(Position P);
    void deleteNext(Position p);
    #endif  


    list.c

    #include"list.h"
    #include<stdlib.h>
    #include"fatal.h"
    
    
    struct  Node {
    	ElementType Element;
    	Position Next;
    };
    
    
    int elementCmp(ElementType e1, ElementType e2) {
    	return e1.Coefficient == e2.Coefficient && e1.Exponent == e2.Exponent;
    }
    
    List CreatList() {
    	List l = malloc(sizeof(struct Node));
    	if (l == NULL)
    		Error("out of memory");
    	l->Next = NULL;
    	return l;
    }
    
    List MakeEmpty(List L) {
    	if (L == NULL)
    		Error("L is not created");
    	DeleteList(L);
    	L->Next = NULL;
    	return L;
    		
    }
    
    int IsEmpty(List L) {
    	return L->Next == NULL;
    }
    
    int IsLast(Position P, List L) {
    	return P->Next == NULL;
    }
    
    Position Find(ElementType X, List L) {
    	Position P;
    	P = L->Next;
    	while (P != NULL&& elementCmp(P->Element, X))
    	{
    		P = P->Next;
    	}
    	return P;
    }
    
    void Delete(ElementType X, List L) {
    	Position P;
    	P = FindPrevious(X, L);
    	if (!IsLast(P, L)) {
    		Position TmpCell = P->Next;
    		P->Next = TmpCell->Next;
    		free(TmpCell);
    	}
    }
    
    Position FindPrevious(ElementType X, List L) {
    	Position P;
    	P = L;
    	while (P->Next != NULL&& elementCmp(P->Next->Element , X))
    		P = P->Next;
    	return P;
    }
    
    void Insert(ElementType X, Position P) {
    	Position tmpCell;
    	tmpCell = (List)malloc(sizeof(struct Node));
    	if (tmpCell == NULL)
    		FatalError("Out of space!!");
    	tmpCell->Element = X;
    	tmpCell->Next = P->Next;
    	P->Next = tmpCell;
    }
    
    void DeleteList(List L) {
    	Position p;
    	p = L->Next;
    	L->Next = NULL;
    	while (p != NULL) {
    		Position tmp;
    		tmp = p->Next;
    		free(p);
    		p = tmp;
    	}
    }
    
    Position Header(List L) {
    	return L;
    }
    
    Position First(List L) {
    	return L->Next;
    }
    
    Position Advance(Position P) {
    	return P->Next;
    }
    
    ElementType Retrieve(Position P) {
    	return P->Element;
    }
    
    void deleteNext(Position p) {
    	Position temp = p->Next->Next;
    	free(p->Next);
    	p->Next = temp;
    }


    Polynomial.h

    #include<stdlib.h>
    #include"list.h"
    
    typedef struct  {
    	List list;
    }Polynomial;
    
    struct  Node {
    	ElementType Element;
    	Position Next;
    };
    
    Polynomial creatPolynomial();
    void insertMonomials(ElementType e,Polynomial poly);
    void inputPolynomial();
    void ZeroPolynomial( Polynomial Poly);
    void AddPolynomial(const  Polynomial Poly1, const  Polynomial Poly2,  Polynomial PolySum);
    void MulPolynomial(const  Polynomial Poly1, const  Polynomial Poly2,  Polynomial PolyProd);
    void printAll(Polynomial poly);

    Polynomial.c

    #include"Polynomial.h"
    #include<stdio.h>
    
    Polynomial creatPolynomial() {
    	Polynomial poly;
    	poly.list = CreatList();
    	return poly;
    }
    
    void insertMonomials(ElementType e, Polynomial poly) {
    	Position p = poly.list;
    	while (Advance(p) != NULL&& Advance(p)->Element.Exponent > e.Exponent)
    		p = Advance(p);
    	if (Advance(p) == NULL) {
    		Insert(e, p);
    	}
    	else if(Advance(p)->Element.Exponent != e.Exponent)
    		Insert(e, p);
    	else{
    		Advance(p)->Element.Coefficient += e.Coefficient;
    		if (Advance(p)->Element.Coefficient == 0)
    			deleteNext(p);
    	}
    }
    
    void inputPolynomial(Polynomial poly) {
    	int coefficient, exponent;
    	ElementType monomials;
    	printf("please enter Coefficient and Exponent,alphabet to end\n");
    	while (scanf("%d", &coefficient) == 1) {
    		scanf("%d", &exponent);
    		monomials.Coefficient = coefficient;
    		monomials.Exponent = exponent;
    		insertMonomials(monomials, poly);
    	}
    	getchar();//字母还留在输入流当中,scanf是不会删去的
    }
    
    
    void ZeroPolynomial(Polynomial Poly) {
    	MakeEmpty(Poly.list);
    }
    
    void AddPolynomial(const  Polynomial Poly1, const  Polynomial Poly2, Polynomial PolySum) {
    	ZeroPolynomial(PolySum);
    	Position p1 = Poly1.list->Next;
    	Position p2 = Poly2.list->Next;
    	Position p3 = PolySum.list;
    	ElementType e;
    	while (p1 && p2) {
    		if (Retrieve(p1).Exponent > Retrieve(p2).Exponent) {
    			Insert(Retrieve(p1), p3);
    			
    			p1 = Advance(p1);
    			p3 = Advance(p3);
    		}
    		else if (Retrieve(p1).Exponent < Retrieve(p2).Exponent) {
    			Insert(Retrieve(p2), p3);
    			p2 = Advance(p2);
    			p3 = Advance(p3);
    		}
    		else {
    			int temp_coefficient = (Retrieve(p1).Coefficient + Retrieve(p2).Coefficient);
    			if (temp_coefficient != 0) {
    				e.Coefficient = temp_coefficient;
    				e.Exponent = Retrieve(p1).Exponent;
    				Insert(e, p3);
    				p1 = Advance(p1);
    				p2 = Advance(p2);
    				p3 = Advance(p3);
    			}
    			else {
    				p1 = Advance(p1);
    				p2 = Advance(p2);
    			}
    		}
    	}
    	Position temp_p;
    	temp_p = (p1) ? p1 : p2;
    	if (temp_p == NULL)
    		return;
    	while (temp_p) {
    		Insert(Retrieve(temp_p), p3);
    		p3 = Advance(p3);
    		temp_p = Advance(temp_p);
    	}
    }
    
    
    void MulPolynomial(const  Polynomial Poly1, const  Polynomial Poly2, Polynomial PolyProd) {
    	ZeroPolynomial(PolyProd);
    	ElementType prod;
    	for (Position i = Poly1.list->Next; i != NULL; i = Advance(i)) {
    		for (Position j = Poly2.list->Next; j != NULL; j = Advance(j)) {
    			prod.Coefficient = Retrieve(i).Coefficient * Retrieve(j).Coefficient;
    			prod.Exponent = Retrieve(i).Exponent + Retrieve(j).Exponent;
    			if (prod.Coefficient != 0)
    				insertMonomials(prod, PolyProd);
    		}
    	}
    }
    
    void printAll(Polynomial poly) {
    	Position p = Advance(poly.list);
    	printf("%dx^%d", Retrieve(p).Coefficient, Retrieve(p).Exponent);
    	p = Advance(p);
    	while (p) {
    		if (Retrieve(p).Coefficient > 0)
    			putchar('+');
    		printf("%dx^%d", Retrieve(p).Coefficient, Retrieve(p).Exponent);
    		p = Advance(p);
    	}
    	printf("\n");
    }

    main.c

    #include"Polynomial.h"
    #include<stdio.h>
    #define N 1208
    
    int main() {
    	Polynomial p1, p2,p3;
    	p1 = creatPolynomial();
    	p2 = creatPolynomial();
    	p3 = creatPolynomial();
    	inputPolynomial(p1);
    	printAll(p1);
    	inputPolynomial(p2);
    	printAll(p2);
    	MulPolynomial(p1, p2, p3);
    	printf("\n");
    	printAll(p3);
    }
    


    展开全文
  • 通过计算行列式的值,对几种Hermite插值多项式的存在唯一性给出另种证明方法,对带不完全导数的m(m≥4)Hermite插值多项式,给出推广的基函数构造方法,并对带不完全导数的三及四Hermite插值多项式的具体实例,给...
  • 最近在看李航的统计学习方法P11时发现一个多项式函数...(第一次写了一版这篇博客,公式自己敲的,但是从别人那里贴的代码,后面感觉那个代码思路没问题,但就是进行了很多次重复计算,数据量大的时候效率低,而且很...

    最近在看李航的统计学习方法P11时发现一个多项式函数拟合问题觉得公式的推导有问题,于是看了一些资料发现这里的推倒是有错误的,用python编程验证后发现按书上的求导结果拟合后的函数图像完全不对,下面给出正确的推导结果和对应的python实现与拟合效果。

    (第一次写了一版这篇博客,公式自己敲的,但是从别人那里贴的代码,后面感觉那个代码思路没问题,但就是进行了很多次重复计算,数据量大的时候效率低,而且很多地方对python的语言特性利用不足,写的有点类似C语言风格,比较晦涩。于是乎,把代码重写了一次,准备把文章撤下来重新贴自己的代码,这时候发现没有保存,前面用Tex敲的一堆公式就没了,心中顿时万马奔腾。。。。好在今天考试考完,强行克服拖延症把这篇文章重写一遍并附上重写的代码。)

    下面开始正文

    问题描述

    假定给定一个训练数据集: 

    T={(x1,y1),(x2,y2),,(xN,yN)}T={(x1,y1),(x2,y2),⋯,(xN,yN)}

    其中,xiRxi∈R是输入xx的观测值,yiRyi∈R是相应的输出y的观测值,i=1,2,,Ni=1,2,⋯,N,多项式函数拟合的任务是假设给定数据由MM次多项式函数生成,选择最有可能产生这些数据的MM次多项式函数,即在MM次多项式函数中选择一个对已知数据以及未知数据都有很好预测能力的函数。

    MM次多项式为

    fM(x,w)=w0+w1x+w2x2++wMxM=j=0MwjxjfM(x,w)=w0+w1x+w2x2+⋯+wMxM=∑j=0Mwjxj

    式中xx式单变量输入,w0,w1,,wmw0,w1,⋯,wmM+1M+1个参数。

    用平方损失作为损失函数,系数1212是为了方便计算,将模型与训练数据代入,有 

    L(w)=12i=1N(j=0Mwjxjiyi)2L(w)=12∑i=1N(∑j=0Mwjxij−yi)2

    wjwj求偏导并令其为00

    书里这里的求导是错误的,就不写错误的推导了,下面给出正确的推导

    set L(w)wk=012i=1N2(j=0Mwjxjiyi)×xki=0i=1Nj=0Mwjxjii=1Nxkiyi(k=0,1,2,,M)set∂ L(w)∂wk=0⇒12∑i=1N2(∑j=0Mwjxij−yi)×xik=0⇒∑i=1N∑j=0Mwjxij=∑i=1Nxikyi(k=0,1,2,⋯,M)

    所以要求拟合多项式系数w0,w1,,wMw0∗,w1∗,⋯,wM∗需要解下面这个线性方程组,下面的求和符号上下限都是i=1i=1NN,为了方便略去不写。

    Nxix2ixMixix2ix3ixM+1ix2ix3ix4ixM+2ixMixM+1ixM+2ix2Miw0w1w2wm=yixiyix2iyixMiyi[N∑xi∑xi2⋯∑xiM∑xi∑xi2∑xi3⋯∑xiM+1∑xi2∑xi3∑xi4⋯∑xiM+2⋮⋮⋮⋱⋯∑xiM∑xiM+1∑xiM+2⋯∑xi2M](w0w1w2⋮wm)=[∑yi∑xiyi∑xi2yi⋮∑xiMyi]

    所以计算出i=1Nxji(j=0,1,2,,2M)∑i=1Nxij(j=0,1,2,⋯,2M)i=1Nxjiyi(j=0,1,2,,M)∑i=1Nxijyi(j=0,1,2,⋯,M)然后将这些值带入上述线性方程组求解即可。

    下面给出python实现

    # coding=utf-8
    
    '''
    作者:Xiaole Wen
    程序:多项式曲线拟合算法
    '''
    import matplotlib.pyplot as plt
    import math
    import numpy
    import random
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    #在这里给出拟合多项式的阶数
    order=9
    
    #生成曲线上的各个点
    x = numpy.arange(-1,1,0.02)
    y = [((a*a-1)*(a*a-1)*(a*a-1)+0.5)*numpy.sin(a*2) for a in x]
    #ax.plot(x,y,color='r',linestyle='-',marker='')
    #,label="(a*a-1)*(a*a-1)*(a*a-1)+0.5"
    plt.plot(x,y)
    #生成的曲线上的各个点偏移一下,并放入到xa,ya中去
    i=0
    xa=[]
    ya=[]
    for xx in x:
        yy=y[i]
        d=float(random.randint(60,140))/100
        #ax.plot([xx*d],[yy*d],color='m',linestyle='',marker='.')
        i+=1
        xa.append(xx*d)
        ya.append(yy*d)
    
    ax.plot(xa,ya,color='m',linestyle='',marker='.')
    #存储从0次到m次的所有冥方和
    bigMat=[]
    for j in range(0,2*order+1):
        sum=0
        for i in range(0,len(xa)):
            sum+=(xa[i]**j)
        bigMat.append(sum)
    
    #计算线性方程组系数矩阵
    matA=[]
    for rowNum in range(0,order+1):
        row=bigMat[rowNum:rowNum+order+1]
        matA.append(row)
    
    matA=numpy.array(matA)
    
    matB=[]
    for i in range(0,order+1):
        ty=0.0
        for k in range(0,len(xa)):
            ty+=ya[k]*(xa[k]**i)
        matB.append(ty)
    
    matB=numpy.array(matB)
    
    matAA=numpy.linalg.solve(matA,matB)
    
    #画出拟合后的曲线
    #print(matAA)
    xxa= numpy.arange(-1,1.06,0.01)
    yya=[]
    for i in range(0,len(xxa)):
        yy=0.0
        for j in range(0,order+1):
            dy=(xxa[i]**j)
            dy*=matAA[j]
            yy+=dy
        yya.append(yy)
    ax.plot(xxa,yya,color='g',linestyle='-',marker='')
    
    ax.legend()
    plt.show()
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    下面给出阶叔分别取3和取9的时候的拟合结果

    图中蓝色的线代表原始数据生成函数,绿色代表拟合函数

    这里写图片描述 
    这里写图片描述

    展开全文
  • 拟合:已知有限个数据点,求近似函数,不要求过已知数据点,只要求在某种...插值方法几种基本的、常用的插值:拉格朗日多项式插值、牛顿插值、分段线性插值、Hermite 插值和三样条插值今天我们就拉格朗日多项式插...
  • 【线性代数】多项式各类算法总结

    千次阅读 2018-04-04 08:30:32
    前言: 这可能是本蒟蒻在2018省选以前写的最难的东西了。 考虑到时间紧迫,所以有些东西我自己也不能完全理解,只能照搬课件。 ...多项式AAA的最高幂,称为该多项式的度,记为degAdegAd...
  • 一次,二次、三次多项式系数解算是工程项目里最常用到的方法,就是常用的数学公式,如果从头写还是比较费劲,涉及到高斯解方程等,这里将源码分享给大家,已经经过大量的测试,解算算法是完全正确的。直接复制即可...
  • 拟合:已知有限个数据点,求近似函数,不要求过已知数据点,只要求在某种...插值方法几种基本的、常用的插值:拉格朗日多项式插值、牛顿插值、分段线性插值、Hermite 插值和三样条插值今天我们就拉格朗日多项式插...
  • 最近在看李航的统计学习方法P11时发现一个多项式函数拟合问题觉得...(第一次写了一版这篇博客,公式自己敲的,但是从别人那里贴的代码,后面感觉那个代码思路没问题,但就是进行了很多次重复计算,数据量大的时候效
  • 1、配方法通过把个解析式利用恒等变形的方法,把其中的某些项配成个或几个多项式正整数幂的和形式解决数学问题的方法,叫配方法。配方法用的最多的是配成完全平方式,它是数学中种重要的恒等变形的方法,它...
  • 1、配方法所谓配方,就是把个解析式利用恒等变形的方法,把其中的某些项配成个或几个多项式正整数幂的和形式。通过配方解决数学问题的方法叫配方法。其中,用的最多的是配成完全平方式。配方法是数学中种...
  • 大意:给定个大小为m的正整数序列和n,问有多少种选法可以凑成n,每个数可以选多,种类不同算不同方案。$n,m,C \leqslant 100000$ 首先处理出生成函数$C$,设答案的形式幂级数为$F$,有递推式$F_n=\sum F_{n-...
  • 一次作业是一个简单的多项式计算,然而对于完全没有接触过面向对象甚至java语言的我来说并不轻松。好在经过一个星期的恶补java语言,我最终还是写出来了一个假面向对象的多项式运算java程序。 类图: 由类图...
  • OO的第一次死亡

    2019-10-03 02:35:45
    一次作业——多项式加减  第一次作业历来是较为简单的,但是对于面向对象零基础的人来说也是有所困惑,到底什么样子的代码才算是面向对象?初次见识java,完全体会不到面向对象的思想,因而在代码编写中透露出...
  • 主函数 1、字符串s可内置于ComeputePoly中,使多项式计算完全封闭 ...在本次作业中出现一次crash报告: 在进行超长字符串判断时,由于开始时未考虑超长字符串会导致正则表达式栈溢出问题,因...
  • 和多数同学一样,多项式相加这一次作业是我第一次接触java语言,也是第一次接触面向对象。我可以说完全没有切换到面向对象的思维模式,只是把c语言里的struct换了个class的名字,所以最大的收获就是熟悉了java的...
  • OO第一次总结

    2018-04-04 00:30:00
     结果还是很客观的,总的说来,第一次作业因为比较简单做的还行;第二次在调度器上犯了一些致命的缺陷,自测的时候又不是很充分所以错了很多;第三次作业完全被Crash掉,究其原因还是因为第二次作业中的BUG加上下来...
  • P问题、NP问题、NP完全问题和NP难问题

    万次阅读 多人点赞 2018-05-24 14:24:38
    在讲P类问题之前先介绍两个个概念:...例如第一次看到的鄙人→_→2、时间复杂度我们知道在计算机算法求解问题当中,经常用时间复杂度和空间复杂度来表示一个算法的运行效率。空间复杂度表示一个算法在计算过程当...
  • 一、 P类问题:能够在多项式时间内解决的 NP类问题:能够在多项式时间内容验证的...e.g:知道解一元二次方程一定可以解一元一次方程 一个问题约化为另一个问题,时间复杂度增加了,问题的应用范围也增大了。 二、 ...
  • OO前三作业总结

    2018-04-03 23:44:00
    多项式加减 1.程序结构 可以看到,程序的Cyclomatic Complexity过高,主要是因为我一些方法内部的分支过多,应该尽量使逻辑更简单,通过适当的分析减少判断的分支数目。 类的设计完全依照讲义上的建议...
  • homogeneous(齐性)

    2019-10-20 12:17:35
    homogeneous(齐性) 世界上没有完全相同的两片树叶 —————Leibniz 、概述 homogeneous在几何上是...在数值分析上是泰勒多项式插值法,即用多项式在一定程度上代替某函数。 homogeneous这个词在数学中翻...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 141
精华内容 56
热门标签
关键字:

一次完全多项式