首先要说明的是本测试系列,除了比较编译效率外,其余所有运行效率的比较都是将matlab的首次运行排出在外,因matlab程序首次运行效率较低。理论上,Forcal程序任意次运行效率都是一样的。不过话又说回来,任意程序包含的函数,有些是需要多次运行的,而有些仅运行一次,甚至一次都不运行,故matlab函数首次运行效率较低应该是一个缺点。但如果说,matlab函数首次运行会对函数进行优化,以后运行效率会显著提高,则matlab函数首次运行效率较低就成了一个优点。
=============
本次演练要用matlab和Forcal实现两个实用函数并进行测试。当然,对脚本来说,这些函数用C/C++或Fortran来实现应是脚本的最佳选择。
=============
1、求解实系数方程组的全选主元高斯消去法:包含大量数组元素存取操作
C/C++代码:
- #include "stdafx.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include "time.h"
- #include "math.h"
- int agaus(double *a,double *b,int n)
- {
- int *js,l,k,i,j,is,p,q;
- double d,t;
- js=new int[n];
- l=1;
- for (k=0;k<=n-2;k++)
- {
- d=0.0;
- for (i=k;i<=n-1;i++)
- {
- for (j=k;j<=n-1;j++)
- {
- t=fabs(a[i*n+j]);
- if (t>d) { d=t; js[k]=j; is=i;}
- }
- }
- if (d+1.0==1.0)
- {
- l=0;
- }
- else
- {
- if (js[k]!=k)
- {
- for (i=0;i<=n-1;i++)
- {
- p=i*n+k; q=i*n+js[k];
- t=a[p]; a[p]=a[q]; a[q]=t;
- }
- }
- if (is!=k)
- {
- for (j=k;j<=n-1;j++)
- {
- p=k*n+j; q=is*n+j;
- t=a[p]; a[p]=a[q]; a[q]=t;
- }
- t=b[k]; b[k]=b[is]; b[is]=t;
- }
- }
- if (l==0)
- {
- delete[] js; printf("fail\n");
- return(0);
- }
- d=a[k*n+k];
- for (j=k+1;j<=n-1;j++)
- {
- p=k*n+j; a[p]=a[p]/d;
- }
- b[k]=b[k]/d;
- for (i=k+1;i<=n-1;i++)
- {
- for (j=k+1;j<=n-1;j++)
- {
- p=i*n+j;
- a[p]=a[p]-a[i*n+k]*a[k*n+j];
- }
- b[i]=b[i]-a[i*n+k]*b[k];
- }
- }
- d=a[(n-1)*n+n-1];
- if (fabs(d)+1.0==1.0)
- {
- delete[] js; printf("fail\n");
- return(0);
- }
- b[n-1]=b[n-1]/d;
- for (i=n-2;i>=0;i--)
- {
- t=0.0;
- for (j=i+1;j<=n-1;j++)
- {
- t=t+a[i*n+j]*b[j];
- }
- b[i]=b[i]-t;
- }
- js[n-1]=n-1;
- for (k=n-1;k>=0;k--)
- {
- if (js[k]!=k)
- {
- t=b[k]; b[k]=b[js[k]]; b[js[k]]=t;
- }
- }
- delete[] js;
- return(1);
- }
-
- int main(int argc, char *argv[])
- {
- int i,j,k;
- double a[4][4]=
- { {0.2368,0.2471,0.2568,1.2671},
- {0.1968,0.2071,1.2168,0.2271},
- {0.1581,1.1675,0.1768,0.1871},
- {1.1161,0.1254,0.1397,0.1490} };
- double b[4]={1.8471,1.7471,1.6471,1.5471};
- double aa[4][4],bb[4];
- clock_t tm;
- tm=clock();
- for(i=0;i<10000;i++)
- {
- for(j=0;j<4;j++)
- {
- for(k=0;k<4;k++)
- {
- aa[j][k]=a[j][k];
- }
- }
- for(j=0;j<4;j++)
- {
- bb[j]=b[j];
- }
- agaus((double *)aa,bb,4);
- }
- printf("循环 %d 次, 耗时 %d 毫秒。\n", i,(clock()-tm));
- for (i=0;i<=3;i++)
- {
- printf("x(%d)=%e\n",i,bb[i]);
- }
- }
复制代码 结果: 循环 10000 次, 耗时 31 毫秒。 x(0)=1.040577e+000 x(1)=9.870508e-001 x(2)=9.350403e-001 x(3)=8.812823e-001
---------
matlab 2009a代码:
- %file agaus.m
- function c=agaus(a,b,n)
- js=linspace(0,0,n);
- l=1;
- for k=1:n-1
- d=0.0;
- for i=k:n
- for j=k:n
- t=abs(a(i,j));
- if (t>d)
- d=t; js(k)=j; is=i;
- end
- end
- end
- if d+1.0==1.0
- l=0;
- else
- if js(k)~=k
- for i=1:n
- t=a(i,k); a(i,k)=a(i,js(k)); a(i,js(k))=t;
- end
- end
- if is~=k
- for j=k:n
- t=a(k,j); a(k,j)=a(is,j); a(is,j)=t;
- end
- t=b(k); b(k)=b(is); b(is)=t;
- end
- end
- if l==0
- printf('fail\n');
- c=[];
- return;
- end
- d=a(k,k);
- for j=k+1:n
- a(k,j)=a(k,j)/d;
- end
- b(k)=b(k)/d;
- for i=k+1:n
- for j=k+1:n
- a(i,j)=a(i,j)-a(i,k)*a(k,j);
- end
- b(i)=b(i)-a(i,k)*b(k);
- end
- end
- d=a(n,n);
- if abs(d)+1.0==1.0
- printf('fail\n');
- c=[];
- return;
- end
- b(n)=b(n)/d;
- for i=n-1:-1:1
- t=0.0;
- for j=i+1:n
- t=t+a(i,j)*b(j);
- end
- b(i)=b(i)-t;
- end
- js(n)=n;
- for k=n:-1:1
- if js(k)~=k
- t=b(k); b(k)=b(js(k)); b(js(k))=t;
- end
- end
- c=b;
- return;
- end
- a=[0.2368,0.2471,0.2568,1.2671;
- 0.1968,0.2071,1.2168,0.2271;
- 0.1581,1.1675,0.1768,0.1871;
- 1.1161,0.1254,0.1397,0.1490] ;
- b=[ 1.8471,1.7471,1.6471,1.5471];
- tic
- for i=1:10000
- c=agaus(a,b,4);
- end
- c
- toc
- c =
- 1.0406 0.9871 0.9350 0.8813
- Elapsed time is 0.762713 seconds.
复制代码 ----------
Forcal代码:
- !using["math","sys"];
- agaus(a,b,n : js,l,k,i,j,is, d,t)=
- {
- oo{ js=array(n)},
- l=1, k=0,
- while{ k<n-1,
- d=0.0, i=k,
- while{ i<n,
- j=k, while{j<n,
- t=abs(a[i,j]),
- if{t>d, d=t, js[k]=j, is=i},
- j++
- },
- i++
- },
- which{ d+1.0==1.0, l=0,
- { if{ (js[k]!=k),
- i=0, while{i<n,
- t=a[i,k], a[i,k]=a[i,js[k]], a[i,js[k]]=t,
- i++
- }
- },
- if{ (is!=k),
- j=k, while{j<n,
- t=a[k,j], a[k,j]=a[is,j], a[is,j]=t,
- j++
- },
- t=b[k], b[k]=b[is], b[is]=t
- }
- }
- },
- if{ (l==0),
- printff("fail\r\n"),
- return(0)
- },
- d=a[k,k],
- j=k+1, while {j<n, a[k,j]=a[k,j]/d, j++},
- b[k]=b[k]/d,
- i=k+1, while {i<n,
- j=k+1, while{j<n,
- a[i,j]=a[i,j]-a[i,k]*a[k,j],
- j++
- },
- b[i]=b[i]-a[i,k]*b[k],
- i++
- },
- k++
- },
- d=a[(n-1),n-1],
- if{ abs(d)+1.0==1.0,
- printff("fail\r\n"),
- return(0)
- },
- b[n-1]=b[n-1]/d,
- i=n-2, while{i>=0,
- t=0.0,
- j=i+1, while{j<n, t=t+a[i,j]*b[j], j++},
- b[i]=b[i]-t,
- i--
- },
- js[n-1]=n-1,
- k=n-1, while{k>=0,
- if{(js[k]!=k), t=b[k], b[k]=b[js[k]], b[js[k]]=t},
- k--
- },
- return(1)
- };
- main(:i,a,b,aa,bb,t0)=
- {
- oo{a=arrayinit{2,4,4 :
- 0.2368,0.2471,0.2568,1.2671,
- 0.1968,0.2071,1.2168,0.2271,
- 0.1581,1.1675,0.1768,0.1871,
- 1.1161,0.1254,0.1397,0.1490},
- b=arrayinit{1,4 : 1.8471,1.7471,1.6471,1.5471},
- aa=array[4,4], bb=array[4]
- },
- t0=clock(),
- i=0, while{i<10000, aa.=a, bb.=b, agaus(aa,bb,4), i++},
- outm[bb],
- [clock()-t0]/1000
- };
复制代码 结果: 1.04058 0.987051 0.93504 0.881282
2.125
Forcal用函数sys::A()对数组元素进行存取:
- !using["math","sys"];
- agaus(a,b,n : js,l,k,i,j,is, d,t)=
- {
- oo{ js=array(n)},
- l=1, k=0,
- while{ k<n-1,
- d=0.0, i=k,
- while{ i<n,
- j=k, while{j<n,
- t=abs(A[a,i,j]),
- if{t>d, d=t, A[js,k]=j, is=i},
- j++
- },
- i++
- },
- which{ d+1.0==1.0, l=0,
- { if{ (A[js,k]!=k),
- i=0, while{i<n,
- t=A[a,i,k], A[a,i,k]=A[a,i,A[js,k]], A[a,i,A[js,k]]=t,
- i++
- }
- },
- if{ (is!=k),
- j=k, while{j<n,
- t=A[a,k,j], A[a,k,j]=A[a,is,j], A[a,is,j]=t,
- j++
- },
- t=A[b,k], A[b,k]=A[b,is], A[b,is]=t
- }
- }
- },
- if{ (l==0),
- printff("fail\r\n"),
- return(0)
- },
- d=A[a,k,k],
- j=k+1, while {j<n, A[a,k,j]=A[a,k,j]/d, j++},
- A[b,k]=A[b,k]/d,
- i=k+1, while {i<n,
- j=k+1, while{j<n,
- A[a,i,j]=A[a,i,j]-A[a,i,k]*A[a,k,j],
- j++
- },
- A[b,i]=A[b,i]-A[a,i,k]*A[b,k],
- i++
- },
- k++
- },
- d=A[a,(n-1),n-1],
- if{ abs(d)+1.0==1.0,
- printff("fail\r\n"),
- return(0)
- },
- A[b,n-1]=A[b,n-1]/d,
- i=n-2, while{i>=0,
- t=0.0,
- j=i+1, while{j<n, t=t+A[a,i,j]*A[b,j], j++},
- A[b,i]=A[b,i]-t,
- i--
- },
- A[js,n-1]=n-1,
- k=n-1, while{k>=0,
- if{(A[js,k]!=k), t=A[b,k], A[b,k]=A[b,A[js,k]], A[b,A[js,k]]=t},
- k--
- },
- return(1)
- };
- main(:i,a,b,aa,bb,t0)=
- {
- oo{a=arrayinit{2,4,4 :
- 0.2368,0.2471,0.2568,1.2671,
- 0.1968,0.2071,1.2168,0.2271,
- 0.1581,1.1675,0.1768,0.1871,
- 1.1161,0.1254,0.1397,0.1490},
- b=arrayinit{1,4 : 1.8471,1.7471,1.6471,1.5471},
- aa=array[4,4], bb=array[4]
- },
- t0=clock(),
- i=0, while{i<10000, aa.=a, bb.=b, agaus(aa,bb,4), i++},
- outm[bb],
- [clock()-t0]/1000
- };
复制代码 结果: 1.04058 0.987051 0.93504 0.881282
1.454
----------
可以看出C/C++、matlab、Forcal耗时之比为 1 :25:68 (Forcal不使用函数sys::A())。 可以看出C/C++、matlab、Forcal耗时之比为 1 :25:47 (Forcal使用函数sys::A())。
本例Forcal耗时较长的原因在于本例程序含有大量的数组元素存取操作。 |