)
系列文章目录文章目录系列文章目录前言一.最大公因式1.定义:2.说明:二.辗转相除法1.带余除法2.引理3.辗转相除法求最大公因数4.辗转相除法求最小公倍数三.C语言实现1.目标2.多项式的传入3.函数传参4.创建变量5.内存交换函数6.返回值的设置7.辗转相除8.化简系数四.完整代码总结前言本系列为使用C语言实现实用的数学公式一.最大公因式1.定义:设f(x),g(x) ∊ P[x]. 若有d(x) ∊ P[x]满足(i) d(x)是f(x)g(x)的公因式.(ii) f(x)g(x)的公因式全是d(x)的因式.则称d(x)为f(x)与g(x)的一个最大公因式.2.说明:最大公因式在相差一个非零常数的意义下是唯一确定的即d₁(x) | d₂(x), d₂(x) | d₁(x)由整除的性质知: d₁(x)c d₂(x).二.辗转相除法1.带余除法设f(x) , g(x) ∊ P[x], g(x) ! 0则存在唯一的多项式q(x), r(x) ∊ P[x]使 f(x) q(x) g(x) r(x) 其中r(x)0 或 ∂(r(x)) ∂(g(x)).称上式中的q(x) 为g(x) 除f (x)的商r(x)为g(x)除f (x)的余式.2.引理设f(x),g(x) ∊ P[x].如果等式f(x) q(x)g(x) r(x)成立则f(x),g(x) 和g(x),r(x)有相同的公因式.(这里毕竟是用C语言去实现该功能感兴趣的朋友可以自行查阅就不在这里证明了)3.辗转相除法求最大公因数//辗转相除法求最大公因数intGCF(intA,intB){while(A%B){inttmpA%B;AB;Btmp;}returnB;}4.辗转相除法求最小公倍数//辗转相除法求最小公倍数intLCM(intA,intB){intAMA;intBMB;intRET0;while(A%B){inttmpA%B;AB;Btmp;}RETAM/B*BM;returnRET;}这里即是让大家了解一下辗转相除法的思想也是帮那些只需要这段代码的朋友们节省时间[doge]三.C语言实现1.目标首先我们的目标是通过带余除法让两个多项式辗转相除法得到一个余式使得这个余式与除式再一次相除依此类推直到得到一个最高次幂为0的余式。这里我们要清楚我们需要一个循环来进行多次相除。2.多项式的传入首先我们面临的第一个问题是如何传入一个多项式很显然同时将各项的系数和次数同时传入一个数组是一件非常困难且混乱的事情。这时我们应该去寻找两个多项式共同具有的特点他们的次数都是0n递增。这里是不是似曾相识啊是的这不就是数组的下标嘛问题迎刃而解我们只需要按照对应的下标储存该次项所对应的系数就行了是不是超级简单!这里我才用的是先输入最高次幂然后依此从高到低输入各次项系数好处就是在输入的时候不会混乱并且简化了输入的难度和代码实现的难度。//多项式一intN10;// 最高次幂longCOE1[20]{0};// 各项系数printf(多项式(一)的最高次幂:);scanf(%d,N1);for(intiN1;i0;i--){printf(请输入 %d 次幂的系数:,i);scanf(%ld,COE1i);}//多项式二intN20;// 最高次幂longCOE2[20]{0};// 各项系数printf(多项式(二)的最高次幂:);scanf(%d,N2);for(intiN2;i0;i--){printf(请输入 %d 次幂的系数:,i);scanf(%ld,COE2i);}3.函数传参写代码要尽量去做到高内聚低耦合并具有较高的可移植性我们不能仅仅为了实现这一个功能让他只能在这个空间内跑动。正如程序员不能只会在一个编译器上敲代码换成个编辑器就什么都不会了。所以当我们时要让他可以在其他程序里运行我们就要将其写成一个函数在需要时随时调用。想做一劳永逸的事情并非那么容易。首先我们要让函数内部知道这个多项式是几次幂这里就用到了我们上一步输入时的最高次幂N1和N2其次传入两个数组。此时问题再一次接踵而至我们需要让他返回一个多项式并且不能破坏原先的数组。在函数内部创建的数组是临时变量你没有办法将地址返回到main里临时变量的生命周期在它所在的函数结束时一并结束。这里我们在传入一个ret用于接收函数运行结果所得的多项式的最高次幂同时一个RET用于接收最大公因式各项的系数。4.创建变量由于我们要确保啊函数的安全运行这里我们对空指针进行一下断言。然后我们原则上不可以改变原先数组的内容我们要重新创建数组将里面的内容拷贝到临时数组中。这里创建的指针MAX和MIN目的是为了确定次数较高的多项式和较低的多项式当MIN MAX时两者进行地址交换。// 返回系数数组 指针函数:(次数1, 系数数组1, 次数2, 系数数组2, 返回次数, 返回系数数组)long*EuclideanAlgorithm(intmax,constlong*COE1,intmin,constlong*COE2,int*ret,long*RET){//空指针断言assert(COE1COE2RET);//创建变量并赋值longM1[20]{0};longM2[20]{0};long*MAXM1;long*MINM2;memcpy(M1,COE1,(max1)*8);memcpy(M2,COE2,(min1)*8);}//判断次数大小if(maxmin){long*TMPMAX;MAXMIN;MINTMP;memchange(max,min,sizeof(max));//内存交换函数}5.内存交换函数内存交换函数这里我选择的是进行每个字节的内存交换 这里实现的时候要之分注意只能交换两个同类型变量的内容。void *可以用来接收任意类型变量的地址len是这两个变量的类型所占bit位数。按找char类型一个bit一个bit进行交换。//内存交换voidmemchange(void*A,void*B,intlen){while(len--){chartmp*(char*)A;*(char*)A*(char*)B;*(char*)Btmp;A(char*)A1;B(char*)B1;}}6.返回值的设置此时的我们先假设功能已经实现完成由于辗转相除往往不能一次就算出最大公因式所以需要用循环语句多次执行。我们不妨假设多项式MAX除以MIN时一下子就出尽了。我们此时此刻并不清楚辗转相除功能是如何实现的所以我们可以选择在步入到辗转相除功能之前将MIN的地址和它系数的值赋给RET和ret就可以了。即使在运行过程中对变量造成改变也不影响RET和ret的返回值。此时此刻我们就有了一个大的框架。long*EuclideanAlgorithm(intmax,constlong*COE1,intmin,constlong*COE2,int*ret,long*RET){//空指针断言assert(COE1COE2RET);//创建变量并赋值longM1[20]{0};longM2[20]{0};long*MAXM1;long*MINM2;memcpy(M1,COE1,(max1)*8);memcpy(M2,COE2,(min1)*8);while(max0){//判断次数大小if(maxmin){long*TMPMAX;MAXMIN;MINTMP;memchange(max,min,sizeof(max));}/* ** 记录返回值 */*retmin;memcpy(RET,MIN,160);//函数功能始/* ** 内容 *///函数功能终}}7.辗转相除现在我们到了最为重要的一步如何实现辗转相除简单来说就是消去MAX的最高次幂那么晚们首先要用到的就是MIN的最高次幂的的系数。条件:存在一个倍数A使得当MIN的最高次幂系数乘以A时必有(MIN的首项系数 * A) (MAX的系数)这样我们就将MAX的最高次幂消去了当然MIN的其余项系数也要乘以A。思路非常明了对不对但是当遇到A为无理数该怎么办你除不尽啊这里我们依然要用到最大公因式的思想我们要做的就是求出这两个最高次幂系数的最大公因数然后让两个系数分别除以最大公因数得出与之对应的倍数num1和num2而num1和num2一定是互素的。接着我们让求出的num1与MIN的各项系数相乘num2与MAX的各项系数相乘这样我们就得到了这两个多项式首项的最小公倍数。由于我的最大公倍数求出来可能会很大所以这里系数用是长整形。这样即达到了消去首项的目的又满足了倍数为一个整数这样是不是让问题变得超级简单了这里我们可以单独写一个求最大公因数的函数。//求最大公因数longGCF(longA,longB){if(AB){memchange(A,B,sizeof(A));}while(A%B){longtmpA%B;AB;Btmp;}returnB;}longnumGCF(MAX[max],MIN[min]);longnum1MAX[max]/num;longnum2MIN[min]/num;for(inti0;max-i1;i){MAX[max-i]*num2;}for(inti0;min-i1;i){MIN[min-i]*num1;}我们现在有了两整理好的多项式只需要让他们相减就可以了在这里我们要对MAX的最高次幂max进行变动所以设置一个临时的Tmax max来替代max。将两式相减后的各项系数重新赋值给MAX如果相减结果为0且比它更高次幂的项系数也为0那么我们就让max–来降低它的最高次数。如果遇到了系数非零的项那么比他次数底但系数为0那么max也将不会再改变。这里我用的是 运算符如果前面条件成立则运算后面条件如果前面条件不成立则不运算后面的条件的特性。//两式相减intstop0;// stop用于自高次向低次遍历两个多项式相减所得的新多项式系数是否为0如果遇到不为0系数则停止遍历longTmaxmax;// max要进行变动创建临时变量Tmax取代max的位置for(inti0;min-i1;i){MAX[Tmax-i]-MIN[min-i];if(!MAX[Tmax-i]!stop!max--){}elseif(MAX[Tmax-i]){stop;}}8.化简系数我们前面用最小公倍数的方法将最高次幂项消去这势必会让系数过大这里我们只需要再次求各项的最大公因数然后让各项除以所得的最大公因数就可以了。intcount*RET;for(inti1;i*ret;i){countGCF(count,*(RETi));}for(inti0;i*ret;i){RET[i]/count;}啊哈这样一步一步走下来是不是让问题变得超级简单了其实问题也没有那么复杂不是吗嘿嘿当然这是用来让大家锻炼一种解决问题的思考方式的大家可千万不要用来偷懒写高代线代的作业啊[doge]四.完整代码#includestdio.h#includestring.h#includeassert.h//实数域多项式求最大公因式//内存交换voidmemchange(void*A,void*B,intlen){while(len--){chartmp*(char*)A;*(char*)A*(char*)B;*(char*)Btmp;A(char*)A1;B(char*)B1;}}//求最大公因数longGCF(longA,longB){if(AB){memchange(A,B,sizeof(A));}while(A%B){longtmpA%B;AB;Btmp;}returnB;}//辗转相除法求多项式的最大公因式// 返回系数数组 指针函数:(次数1, 系数数组1, 次数2, 系数数组2, 返回次数, 返回系数数组)long*EuclideanAlgorithm(intmax,long*COE1,intmin,long*COE2,int*ret,long*RET){//空指针断言assert(COE1COE2RET);//创建变量并赋值longM1[20]{0};longM2[20]{0};long*MAXM1;long*MINM2;memcpy(M1,COE1,(max1)*8);memcpy(M2,COE2,(min1)*8);while(max0){//判断次数大小if(maxmin){long*TMPMAX;MAXMIN;MINTMP;memchange(max,min,sizeof(max));}/* ** 记录返回值 */*retmin;memcpy(RET,MIN,160);/* ** 最小公倍数 */longnumGCF(MAX[max],MIN[min]);longnum1MAX[max]/num;longnum2MIN[min]/num;for(inti0;max-i1;i){MAX[max-i]*num2;}for(inti0;min-i1;i){MIN[min-i]*num1;}/* ** 两式相减 */intstop0;// stop用于自高次向低次遍历两个多项式相减所得的新多项式系数是否为0如果遇到不为0系数则停止遍历longTmaxmax;// max要进行变动创建临时变量Tmax取代max的位置for(inti0;min-i1;i){MAX[Tmax-i]-MIN[min-i];if(!MAX[Tmax-i]!stop!max--){}elseif(MAX[Tmax-i]){stop;}}}//化简系数intcount*RET;for(inti1;i*ret;i){countGCF(count,*(RETi));}for(inti0;i*ret;i){RET[i]/count;}returnRET;}intmain(){//多项式一intN10;// 最高次幂longCOE1[20]{0};// 各项系数printf(多项式(一)的最高次幂:);scanf(%d,N1);for(intiN1;i0;i--){printf(请输入 %d 次幂的系数:,i);scanf(%ld,COE1i);}//多项式二intN20;// 最高次幂longCOE2[20]{0};// 各项系数printf(多项式(二)的最高次幂:);scanf(%d,N2);for(intiN2;i0;i--){printf(请输入 %d 次幂的系数:,i);scanf(%ld,COE2i);}//函数传惨intret0;//接收返回多项式的最高次数longRET[20]{0};//接收返回的多项式EuclideanAlgorithm(N1,COE1,N2,COE2,ret,RET);//打印多项式的系数ret1;while(ret--){printf(%d次方的系数为:%ld\n,ret,RET[ret]);}return0;}总结本文详细讲述了线性代数中求多项式的最大公因式的方法未来博主会继续更新相关数学函数的实现欢迎大家交流学习。