LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1128|回复: 13

我编的c语言“线性代数”处理函数,虚心接受哥哥姐姐的指教

[复制链接]
发表于 2008-7-28 11:27:20 | 显示全部楼层 |阅读模式
也算是开源吧!!!!!!
刚刚学习c语言,代码难免有很多不足。
若能得到您的改进,感激不尽!!!!!
以下代码用gcc4编译都能顺利执行,并且结果正确。

代码在2楼
函数说明在3楼
 楼主| 发表于 2008-7-28 11:28:06 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #include <stdlib.h>
  4. int cofactor(int n,double *p,int k,int l)
  5. {
  6. int i,j,h,m;
  7. for(i=0,h=0;i<n;i++)
  8. {
  9.   if(i==k)continue;
  10.   for(j=0;j<n;j++,h++)
  11.   {
  12.    if(j==l){h--;continue;}
  13.    p[h]=p[i*n+j];
  14.   }
  15. }
  16. m=n-1;
  17. return m;
  18. }
  19. double value_det(int n,double *det)
  20. {
  21. int maxi,maxj,i,j;
  22. double value=1,*p;p=NULL;
  23. i=0;
  24. do
  25. {
  26.   i++;
  27.   p=(double *)malloc(n*n*sizeof(double));
  28.   if(i>100){printf("function value_det() failed because malloc()!\n");exit(0);}
  29. }
  30. while(p==NULL);
  31.   for(i=0;i<n*n;i++)p[i]=det[i];
  32.   while(1)
  33.   {
  34.    if(n>=3)
  35.    {
  36.     for(i=0,maxi=0,maxj=0;i<n;i++)for(j=0;j<n;j++)if(p[i*n+j]>p[maxi*n+maxj]){maxi=i;maxj=j;}
  37.     for(i=0,j=0;i<n;i++)if(p[maxi*n+i]==0)j++;
  38.     for(i=0;i<n;i++)if(p[i*n+maxj]==0)j--;
  39.     if(j>=0)
  40.     {
  41.      for(j=0;j<n;j++)
  42.      {
  43.       if(j==maxj||p[maxi*n+j]==0)continue;
  44.       for(i=0;i<n;i++)
  45.       {
  46.        if(i==maxi)continue;
  47.        p[i*n+j]=p[i*n+j]-p[i*n+maxj]*p[maxi*n+j]/p[maxi*n+maxj];
  48.       }
  49.      }
  50.     }
  51.     else {
  52.           for(i=0;i<n;i++)
  53.           {
  54.            if(i==maxi||p[i*n+maxj]==0)continue;
  55.            for(j=0;j<n;j++)
  56.            {
  57.             if(j==maxj)continue;
  58.                    p[i*n+j]=p[i*n+j]-p[maxi*n+j]*p[i*n+maxj]/p[maxi*n+maxj];
  59.            }
  60.           }
  61.          }
  62.     if((maxi+maxj)%2==1)value*=-1;
  63.     value*=p[maxi*n+maxj];
  64.     n=cofactor(n,p,maxi,maxj);
  65.    }
  66.    else if(n==2){value*=(p[0]*p[3]-p[1]*p[2]);break;}
  67.         else if(n==1){value*=p[0];break;}
  68.   }
  69.   free(p);
  70. return value;
  71. }
  72. double *solve_cramer(int n,double *mtr)
  73. {
  74. double *x,*p,d;
  75. int i=0,j,k;
  76. do
  77. {i++;
  78.   x=(double *)malloc(n*sizeof(double));
  79.   if(i>100){printf("function solve_cramer() failed because malloc()!\n");exit(0);}
  80. }
  81. while(x==NULL);i=0;
  82. do
  83. {i++;
  84.   p=(double *)malloc(n*n*sizeof(double));
  85.   if(i>100){printf("function solve_cramer() failed because malloc()!\n");exit(0);}
  86. }
  87. while(p==NULL);
  88. for(j=0,k=0;k<n*n;j++){if((j+1)%(n+1)==0)continue;p[k]=mtr[j];k++;}
  89. d=value_det(n,p);
  90. if(d==0){free(x);x=NULL;}
  91. else
  92. {
  93.   for(i=0;i<n;i++)
  94.   {
  95.    for(j=0,k=0;k<n*n;j++){if((j+1)%(n+1)==0)continue;p[k]=mtr[j];k++;}
  96.    for(k=0;k<n;k++)p[k*n+i]=mtr[k*(n+1)+n];
  97.    x[i]=value_det(n,p)/d;
  98.   }
  99. }
  100. free(p);
  101. return x;
  102. }
  103. double *multiply_mtr(double *mtr1,double *mtr2,int m,int s,int n)
  104. {
  105. double *p1,*p2,*p;
  106. int i=0,k,j;
  107. do
  108. {
  109.   i++;
  110.   p1=(double *)malloc(m*s*sizeof(double));
  111.   if(i>100){printf("function multiply_mtr() failed because malloc()!\n");exit(0);}
  112. }
  113. while(p1==NULL);i=0;
  114. do
  115. {
  116.   i++;
  117.   p2=(double *)malloc(n*s*sizeof(double));
  118.   if(i>100){printf("function multiply_mtr() failed because malloc()!\n");exit(0);}
  119. }
  120. while(p2==NULL);i=0;
  121. do
  122. {
  123.   i++;
  124.   p=(double *)malloc(m*n*sizeof(double));
  125.   if(i>100){printf("function multiply_mtr() failed because malloc()!\n");exit(0);}
  126. }
  127. while(p==NULL);
  128. for(i=0;i<m*s;i++)p1[i]=mtr1[i];
  129. for(i=0;i<s*n;i++)p2[i]=mtr2[i];
  130. for(i=0;i<m*n;i++)p[i]=0;
  131. for(i=0;i<m;i++)
  132. {
  133.   for(j=0;j<n;j++)
  134.   {
  135.    for(k=0;k<s;k++)p[i*n+j]+=p1[i*s+k]*p2[k*n+j];
  136.   }
  137. }
  138. free(p1);
  139. free(p2);
  140. return p;
  141. }
  142. double *transp_mtr(double *mtr,int m,int n)
  143. {
  144. double *p;
  145. int i=0,j;
  146. do
  147. {i++;
  148.   p=(double *)malloc(m*n*sizeof(double));
  149.   if(i>100){printf("function transp_mtr() failed by malloc()!\n");exit(0);}
  150. }
  151. while(p==NULL);
  152. for(i=0;i<n;i++)
  153.   for(j=0;j<m;j++)
  154.    p[i*m+j]=mtr[j*n+i];
  155. return p;
  156. }
  157. double *inv_mtr(double *mtr,int n)
  158. {
  159. int i=0,j,k;
  160. double *inver,*p,a;
  161. inver=NULL;
  162. p=NULL;
  163. do
  164. {i++;
  165.   inver=(double *)malloc(n*n*sizeof(double));
  166.   if(i>100){printf("function inv_mtr() failed by malloc()!\n");exit(0);}
  167. }
  168. while(inver==NULL);i=0;
  169. do
  170. {i++;
  171.   p=(double *)malloc(n*n*sizeof(double));
  172.   if(i>100){printf("function inv_mtr() failed by malloc()!\n");exit(0);}
  173. }
  174. while(p==NULL);
  175. for(i=0;i<n*n;i++)p[i]=mtr[i];
  176. if(value_det(n,p)==0){printf("no inverse of the matrix\n");free(p);free(inver);inver=NULL;}
  177. else
  178. {
  179.   for(i=0;i<n;i++)
  180.   {
  181.    for(j=0;j<n;j++)
  182.    {
  183.     for(k=0;k<n*n;k++)p[k]=mtr[k];
  184.     k=cofactor(n,p,i,j);
  185.     inver[i*n+j]=value_det(k,p);
  186.     if((i+j)%2==1)inver[i*n+j]*=-1;
  187.    }
  188.   }
  189.   free(p);
  190.   p=inver;
  191.   inver=transp_mtr(p,n,n);
  192.   free(p);
  193.   a=value_det(n,mtr);
  194.   for(i=0;i<n*n;i++)inver[i]/=a;
  195. }
  196. return inver;
  197. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-28 11:28:48 | 显示全部楼层
int cofactor(int n,double *p,int k,int l)
求n阶行列式除去k行l列後的余子式(处理时注意下标)。传送数组的首地址给double *p。返回处理後行列式的阶数。
===========================================================
double value_det(int n,doulbe *p)
求n阶行列式的值。传送数组的首地址给double *p。返回行列式的值。
===========================================================
double *solve_cramer(int n,double *mtr)
用克拉默法则解含有n个未知数的线性方程组,即系数行列式为n阶。将存放增广矩阵的数组首地址传送给double *mtr,返回存放n个解的数组的首地址。若无解返回NULL。
===========================================================
double *multiply_mtr(double *mtr1,double *mtr2,int m,int s,int n)
计算m*s与s*n两矩阵相乘,将存放两矩阵的数组的首地址分别传给double *mtr1和double *mtr2。返回计算後的矩阵首地址。
===========================================================
double *transp_mtr(double *mtr,int m,int n)
矩阵转置。将存放m*n矩阵的数组的首地址传送给double *mtr。返回存放转置後的矩阵的首地址。
===========================================================
double *inv_mtr(double *mtr,int n)
求n阶矩阵的逆矩阵,返回存放逆矩阵的数组首地址。若无逆矩阵返回NULL。
n>=2
回复 支持 反对

使用道具 举报

发表于 2008-7-28 12:13:41 | 显示全部楼层
提个代码风格的建议, 个人认为 do-while 循环写成楼主这样有点别扭. 很多人喜欢写成下面的形式

  1. do {
  2. } while ();
复制代码

重点在于, while() 和 } 写在一行让人一眼就看得出它不是一个 while 循环, 而是 do-while 循环
回复 支持 反对

使用道具 举报

发表于 2008-7-28 12:20:02 | 显示全部楼层
另外, 在 malloc 失败的时候进行循环重试似乎意义并不是太大. 根据 man malloc 来看, malloc 并不会受到 signal 干扰而失败, 唯一提到的可能的失败情况是 ENOMEM, 这种情况下, 重试也没什么用
回复 支持 反对

使用道具 举报

发表于 2008-7-28 12:24:24 | 显示全部楼层
像这样的批量赋值

  1. for(i=0;i<m*s;i++)p1[i]=mtr1[i];
复制代码

如果用块拷贝的方式会有更高的效率, 毕竟是数学库嘛, 效率还是比较重要的. 或者说, 有什么别的需要考虑的因素吗?

  1. memcpy(p1, mtr1, m * s * sizeof(*mtr1));
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-28 12:34:47 | 显示全部楼层
Post by remote fish;1879410
像这样的批量赋值
  1. for(i=0;i<m*s;i++)p1[i]=mtr1[i];
复制代码
如果用块拷贝的方式会有更高的效率, 毕竟是数学库嘛, 效率还是比较重要的. 或者说, 有什么别的需要考虑的因素吗?
  1. memcpy(p1, mtr1, m * s * sizeof(*mtr1));
复制代码

这个太好了,
我都不知道有这个函数,去学习下!!!
十分感谢


这个就是开源的好处,呵呵
回复 支持 反对

使用道具 举报

发表于 2008-7-28 12:40:00 | 显示全部楼层
回得真快. 楼主再看看 man memset 的说明吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-28 12:45:55 | 显示全部楼层
Post by remote fish;1879415
回得真快. 楼主再看看 man memset 的说明吧


是在shell下执行$man memset吗?
就是这样了!!!
xin@debian:~$ man memset
No manual entry for memset
xin@debian:~$
回复 支持 反对

使用道具 举报

发表于 2008-7-28 13:15:42 | 显示全部楼层
debian 默认没有装 glibc 的 manpages
手工装一下吧, 好像是 manpages-dev 这个包. 记不清了

  1. sudo aptitude install manpages-dev
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表