通用的数学表达式编译计算动态库FORCALDLL.DLL
为了进行某些数值计算,您是否还在不得不借助于FORTRAN(或C/C++)编译器?虽然,对于运算量特别巨大的工程,您还是需要这么做的,但是,对于众多的中小型运算,您可能早已不胜其烦。令人欣喜的是,现在有了FORCALDLL.DLL,您可以在软件中自由地添加各种数值计算功能,享受到一劳永逸之乐趣。 FORCALDLL.DLL是基于FORCAL技术构建的,可以获得最优化的执行代码和最快的执行速度。在这里,我们可以把FORCALDLL.DLL和FORCAL看成一回事而不加以区分。 以下是有关FORCAL的详细说明。
导读:
1、认识FORCALDLL.DLL:介绍FORCAL的主要功能和用法,包括FORCAL动态库的输出函数说明。 2、FORCAL的二级函数:包括数据类型函数、逻辑函数、流程控制函数和一些常用数学函数等,极大地扩展了FORCAL的数值计算功能。 3、实例程序及源代码[forcaltest.exe]:这是一个由FORCALDLL.DLL支持的数值计算程序,用于全面演示FORCAL的函数包括所有的二级函数以及自定义外部函数的用法。在该程序中,你可以看到如何向FORCAL添加可由FORCAL调用的外部函数。同时,该程序中的一个自定义外部函数speed()比较了FORCAL和VC的执行速度。
正文:
--------------------------------1-------------------------------
一、认识FORCALDLL.DLL
FORCALDLL.DLL是一个通用的数学表达式编译计算动态库,基于FORCAL技术构建,以下将简称为FORCAL。 (一)、FORCAL表达式: FORCAL可以编译计算的数学表达式格式如下: 格式1:F(x,y,x1,... ...)=1-x+sin[x1]-... ... 格式2:()=2+3*ln[3.45] 格式3:2+3*ln[3.45] 格式4:F(x,y)=2+sin[aa]+cos[aa-x]+bb,aa=3*ln[y-bb],bb=x+y+x*y 格式5:{F(x,y)=2+sin[aa]+cos[aa-x]+bb,aa=3*ln[y-bb],bb=x+y+x*y} 格式1:F 为函数名,可为任意字符,或者缺省;自变量放在小括号( )内,有多个自变量时,自变量间以逗号分隔,自变量为以小写英文字母开头的任意小写英文字母与数字的组合,自变量个数可以为零;等号后为函数式,不可缺省。 格式2和格式3是等效的,均表示无参函数。 格式4:数学表达式的可优化表示形式。aa、bb为符号定义名,其命名方式与自变量相同且不能与任何一个自变量同名。该格式的计算顺序为从右向左,即:先计算bb,然后计算aa,最后计算F(x,y)并把该值作为整个表达式的值。 格式5表示可以将表达式放在一对括号( )、[ ]或{ }内。 函数式中的运算符有加号'+'、减号'-'、乘号'*'、除号'/'和乘方'^'五种。注意数字与自变量相乘时,乘号不可省略;在进行乘方运算时,底数应为非负数。函数式中可以用三对括号( )、[ ]和{ }。 FORCAL表达式有实数表达式和复数表达式两种。 实数表达式中可以使用的基本函数如下: 一级函数:平方根sq,指数函数exp,常用对数lg,自然对数ln,正弦sin,余弦cos,正切tg,反正弦as,反余弦ac,反正切at,双曲正弦sh,双曲余弦ch,双曲正切th,取整函数int,绝对值abs。 二级函数:请参见说明的第二部分。这些二级函数包括数据类型函数、逻辑函数、流程控制函数和一些常用数学函数等,极大地扩展了FORCAL的数值计算功能。 复数表达式中可以使用的基本函数如下: 平方根sq,指数函数exp,自然对数ln,正弦sin,余弦cos,取整函数int,绝对值abs,共轭函数con。 复数举例:2+3i。 复数表达式举例:F(x,y,... ...)=2+3i-sin[x-i]*ln[y]- ... ... 。 在复数表达式中不能使用 i 作为自变量,因为 i 已经用来表示虚数。 另外,FORCAL编译器在编译表达式时能进行两种形式的代码优化,其一是预先计算表达式中可以计算的部分,其二是采用格式4表示的数学表达式的可优化形式。 FORCAL将最大限度地进行第一种代码优化,但这种自动进行的优化并不彻底,若要获得最优化的代码,您需要将表达式中可以计算的部分用括号括起来(一般情况下不需要这样做)。 例如:要想进行彻底的第一种代码优化,需要将式子: F(x,y)=x-5-7+y 写成:F(x,y)=x-[5+7]+y或F(x,y)=x+[-5-7]+y 需要注意的是,在进行第一种代码优化时,只有一级函数可以进行预先计算,二级函数的计算始终只能在编译后的表达式中进行。 FORCAL的第二种代码优化可以保证表达式中的任何相同部分只进行一次计算,从而最大限度地提高了计算速度。 在FORCALDLL.DLL 试用版中只有实数计算功能,以后将增加复数计算功能。 (二)、FORCAL的速度: 由于编译表达式所占的时间很少,所以这里只比较FORCAL与FORTRAN(或C/C++)的计算速度。 1、对纯数学表达式计算速度的比较 FORCAL是由FORTRAN(或C/C++)的编译程序生成的,所以它的速度要稍慢些,约为FORTRAN(或C/C++)的编译速度的50%左右。一般,表达式越长越复杂,FORCAL与FORTRAN(或C/C++)的计算速度就越接近。 2、综合比较 综合比较是指由FORCAL生成的实用程序和由FORTRAN(或C/C++)直接生成的实用程序的速度的比较。在实用程序中,除了计算表达式外,还有很多的算法处理,这使得它们之间的速度差别在缩小,毋庸质疑,算法处理所占的时间越长,它们的速度差别就越小。另外,启动FORTRAN(或C/C++)编译程序进行编译和出错调试等要占用一定的时间,这些时间要远比使用FORCAL进行同样的工作所用的时间要长。所以,综合来看,除了运算量特别巨大的程序,使用FORCAL要比使用FORTRAN(或C/C++)进行计算要快。 3、FORCAL的速度还能提高吗 回答是肯定的。因为FORCAL系统由编译和计算两部分组成,它编译数学表达式后的代码质量是非常高的,但目前使用的FORCAL由FORTRAN(或C/C++)生成,这使得FORCAL的计算代码中有些是不必要的,白白增加了执行时间。所以,如果FORCAL的计算部分用汇编语言来写,将能加快它的执行速度;如果让计算机的数学协处理器来执行FORCAL的计算部分,将能把FORCAL的计算速度推向极至。 (三)、FORCALDLL.DLL中的动态库函数说明: (1)、版本信息函数:const char *ver(void) [序列号:1]。 (2)、表达式个数设置函数:bool setfornum(int m) [序列号:2]: 设置FORCALDLL.DLL可同时使用的表达式的个数为m个,设置成功函数返回true。可多次调用该函数。 注意:表达式从0开始编号,取值范围为0到m-1,编号为i的表达式称第i个表达式或者表达式i。 (3)、编译表达式:int rcom(int m,char a[],int &n) [序列号:3]: 编译第m个表达式a,返回的自变量个数为n个,当n=-1时表示有0个自变量,当n=0时表示有1个自变量,当n=1时表示有2个自变量,依次类推。 该函数返回值的意义如下: 0:表达式正确,编译通过; 1:不正确的运算方式; 2:无表达式; 3:自变量说明错,等号前有非法字符; 4:自变量应放在 ( ) 内; 5:非法自变量字符(以小写英文字母开头的小写英文字母与数字的组合); 6:自变量以小写英文字母开头; 7:自变量重复说明; 8:括号不成对; 9:在复数计算时,不能用 i 作为自变量(该返回值在编译复数表达式时使用); 10:不可识别函数名; 11:数学表达式太长,接近32766个字符; 12:不可识别自变量; 13:数字错误; 14:不可识别字符或一级函数有多个自变量; 15:内存分配失败; 16:二级函数错误; 17:符号定义错误或无表达式; 18:超出普及版允许的字符限制,请注册使用标准版。[在标准版中无此返回值] (4)、计算表达式的值:double rcal(int m,double a[]) [序列号:4]: 计算第m个表达式的值,数组a中依次存放自变量。 (5)、释放动态库所申请的空间:void freedll(void) [序列号:5]。 (6)、动态库错误函数:int fcerr(char *&errname) [序列号:6]: 该函数在使用rcal或rcals函数后调用,返回动态库的第一个运行错误,fcerr返回错误类型,errname返回出错函数名,该函数被调用后,将把错误类型重新设置为0。 通常,可以在主程序中用int matherr(struct _exception *err)检测标准数学错误,用int fcerr(*&)检测FORCAL运行错误;特别地,可以用testdouble[或finite]和fcerr检测所有错误。 (7)、获得自变量数组指针函数:double *getin(int m) [序列号:7]: 该函数获得指向第m个表达式的自变量数组的指针,可用来输入自变量。 (8)、计算表达式的值:double rcals(int m) [序列号:8]: 计算第m个表达式的值,假定自变量已经通过自变量数组指针getin或getallin输入。该函数与getin或getallin配合使用,计算速度比rcal要快。 (9)、获得一维存储数组double的指针:double *getfcdoubles(long &n) [序列号:9]: 整数n返回该数组的大小。 (10)、获得多维存储数组doublearray的指针:double **getfcdoublearrays(long &n,long *&m) [序列号:10]: 整数n返回该数组的大小,m返回存放各维数组长度的整数组的指针。 (11)、设置可由FORCAL调用的外部函数:bool setfcfun(char **pch,int *n,double (**fun)(int k,double *dd)) [序列号:11]: 字符串表指针pch指出外部函数名,串表的最后应是一个空名,表示该串表的结束;整数数组n的对应项存放每个函数的自变量个数,其中-2表示有不确定的多个自变量,-1表示有0个自变量,0表示有1个自变量,依次类推;指向函数指针数组的指针fun指出每一个对应的函数,每个函数有两个相同的变量,其中dd为一个存放自变量的双精度数组,k为该数组的长度-1。 设置成功函数返回true,否则返回false。 例如: char *pch[]={"asd","aa2a",""}; file://asd和aa2a为两个函数名; int n[]={1,0}; file://1表示有2个自变量,0表示有1个自变量; double (*fun[])(int ,double *)={asd,aa2a}; file://asd和aa2a为两个完成某种计算的函数; 利用该函数可以向FORCAL无缝地添加各种基本函数,FORCAL将把这些函数当作二级函数进行处理。在设计这些函数时,需要注意两个问题,一是要用setfcerr()向FORCAL报告运行错误,二是函数的参数中若使用表达式作自变量[例如:simpintegrate()],要注意避免无穷递归调用。 (12)、设置自定义外部函数的运行错误:void setfcerr(int n,char *ch) [序列号:12]: 整数n指出错误类型号,字符串指针ch指向出错函数名。该函数向FORCAL报告运行错误。 (13)、获得指向存放各表达式的自变量的指针数组的指针:double **getallin(void) [序列号:13]: 例如:double **aa=getallin(); 则aa[3]为第3个表达式的自变量数组指针,可用来输入自变量。 (14)、获得动态库运行错误的类型:int fcerrnum(void) [序列号:14]: 该函数不改变错误类型的设置。 (15)、获得指向表示表达式是否编译成功的数组的指针:bool *getfortrue(void) [序列号:15]: 该数组记录了表达式的编译状态,当数组元素为true时,表示其对应的表达式编译通过。 (16)、获得指向存放各个表达式的自变量的个数的整数数组的指针:int *getvarnum(void) [序列号:16]: 该数组记录了各个表达式的自变量个数。
以下函数使用_stdcall修饰符输出,可以在VB、delphi等高级语言中使用,用法参见1~16函数:
(17)、const char * _stdcall STDver(void); [序列号:17] (18)、bool _stdcall STDsetfornum(int); [序列号:18] (19)、void _stdcall STDfreedll(void); [序列号:19] (20)、int _stdcall STDrcom(int ,char [],int &); [序列号:20] (21)、double _stdcall STDrcal(int ,double []); [序列号:21] (22)、double * _stdcall STDgetin(int ); [序列号:22] (23)、double _stdcall STDrcals(int ); [序列号:23] (24)、double * _stdcall STDgetfcdoubles(long &); [序列号:24] (25)、double ** _stdcall STDgetfcdoublearrays(long &,long *&); [序列号:25] (26)、bool _stdcall STDsetfcfun(char **,int *,double (**)(int ,double *)); [序列号:26] (27)、double ** _stdcall STDgetallin(void); [序列号:27] (28)、bool * _stdcall STDgetfortrue(void); [序列号:28] (29)、int * _stdcall STDgetvarnum(void); [序列号:29] (30)、int _stdcall STDfcerr(char *&); [序列号:30] (31)、int _stdcall STDfcerrnum(void); [序列号:31] (32)、void _stdcall STDsetfcerr(int ,char *); [序列号:32]
----------------------------------2-----------------------------
二、FORCAL的二级函数
说明:
在以下说明中,fcerr为动态库函数运行错误代码,int(m)表示取实数m的整数部分。 FORCAL可设置同时使用多个表达式,假如设置了n个表达式,则表达式的序号分别为0、1、2、...、 i、 ...、n-1,第i个表达式简称为表达式i。 部分函数的举例请参见本文第三部分:实例程序及源代码[forcaltest.exe]。
1、数据类型函数:
1.1、设置多个双精度实数 newdoubles(m): 该函数设置int(m)个双精度实数,若int(m)<1,则删除这些双精度实数,该函数总是返回0。 这些双精度实数从0开始编号,即:0,1,2,3,... ...,m-1。 若fcerr=1,设置失败。 以下这些函数可以对这些双精度实数进行各种运算操作。 1.1.1、对一个双精度实数进行赋值 setd(n,x): 将第int(n)个双精度实数的值设为x,该函数返回x的值。 若fcerr=1,表示不存在第int(n)个双精度实数。 函数ssetd(n,x)与setd(n,x)完成相同的功能,但不对第int(n)个双精度实数的存在性进行检查,若n值非法将导致不可预知的错误。ssetd(n,x)比setd(n,x)的速度要快。 1.1.2、获得一个双精度实数的值 getd(n): 获得第int(n)个双精度实数的值。 若fcerr=1,表示不存在第int(n)个双精度实数。 函数ggetd(n,x)与getd(n,x)完成相同的功能,但不对第int(n)个双精度实数的存在性进行检查,若n值非法将导致不可预知的错误。ggetd(n,x)比getd(n,x)的速度要快。 1.1.3、将一个数加到一个双精度实数上并返回相加后的值 addgetd(n,x): 先将x加到第int(n)个双精度实数上,然后返回相加后的值。 若fcerr=1,表示不存在第int(n)个双精度实数。 函数aaddgetd(n,x)与addgetd(n,x)完成相同的功能,但不对第int(n)个双精度实数的存在性进行检查,若n值非法将导致不可预知的错误。aaddgetd(n,x)比addgetd(n,x)的速度要快。 1.1.4、获得一个双精度实数的值后再将另一个数加到该双精度实数上 getdadd(n,x): 该函数先返回第int(n)个双精度实数的值,然后将x加到第int(n)个双精度实数上。 若fcerr=1,表示不存在第int(n)个双精度实数。 函数ggetdadd(n,x)与getdadd(n,x)完成相同的功能,但不对第int(n)个双精度实数的存在性进行检查,若n值非法将导致不可预知的错误。ggetdadd(n,x)比getdadd(n,x)的速度要快。
1.2、设置多个一维双精度实数数组 newdoublearrays(m): 该函数设置int(m)个一维双精度实数数组,若int(m)<1,则删除这些双精度实数数组,该函数总是返回0。 这些双精度实数数组从0开始编号,即:0,1,2,3,... ...,m-1。 若fcerr=1,设置失败。 以下这些函数可以对这些双精度实数数组或数组元素进行各种运算操作。 1.2.1、设置一维双精度实数数组的长度 newdoublearray(n,m,x1,x2,... ...): 将第int(n)个数组长度设为int(m),可以存储int(m)个数组元素,若int(m)<1,则删除该数组,该函数总是返回0。 这些数组的元素从0开始编号,即:0,1,2,3,... ...,m-1。 设置成功将x1,x2,... ...存储到该数组。 若fcerr=1:参数个数不能少于两个;fcerr=2:未设置多个一维双精度实数数组;fcerr=3:不存在第int(n)个双精度数组;fcerr=4:数组设置失败;fcerr=5:x1,x2,... ...的个数大于m。 1.2.2、对一个数组元素进行赋值 setda(n,m,x): 该函数将x值存储到第int(n)个数组的第int[m]个元素位置并返回x的值。 若fcerr=1:未设置多个一维双精度实数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。 函数ssetda(n,m,x)与setda(n,m,x)完成相同的功能,但该函数不对数组元素的存在性进行检查,若数组元素不存在将导致不可预知的错误。ssetda(n,m,x)比setda(n,m,x)的速度要快。 1.2.3、获得一个数组元素的值 getda(n,m): 该函数获得第int(n)个数组的第int[m]个数组元素的值。 若fcerr=1:未设置多个一维双精度实数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。 函数ggetda(n,m)与getda(n,m)完成相同的功能,但该函数不对数组元素的存在性进行检查,若数组元素不存在将导致不可预知的错误。ggetda(n,m)比getda(n,m)的速度要快。 1.2.4、将一个数加到一个数组元素上并返回相加后的值 addgetda(n,m,x): 先将x加到第int(n)个数组的第int[m]个数组元素上,然后返回相加后的值。 若fcerr=1:未设置多个一维双精度实数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。 函数aaddgetda(n,m,x)与addgetda(n,m,x)完成相同的功能,但该函数不对数组元素的存在性进行检查,若数组元素不存在将导致不可预知的错误。aaddgetda(n,m,x)比addgetda(n,m,x)的速度要快。
2、逻辑函数:
FORCAL用大于0的数表示逻辑真,小于等于0的数表示逻辑假。
2.1、gt(x,y):如果x>y返回1,否则返回-1。 2.2、ge(x,y):如果x>=y返回1,否则返回-1。 2.3、lt(x,y):如果x<y返回1,否则返回-1。 2.4、le(x,y):如果x<=y返回1,否则返回-1。 2.5、eq(x,y):如果x==y返回1,否则返回-1。 2.6、ne(x,y):如果x!=y返回1,否则返回-1。 2.7、and(x,y):如果x>0同时y>0返回1,否则返回-1。 2.8、or(x,y):如果x<0同时y<0返回-1,否则返回1。 2.9、not(x):如果x>0返回-1,否则返回1。 2.10、xor(x,y):如果x和y符号相同返回-1,否则返回1。
3、表达式相互调用及流程控制函数:
3.1、for循环函数 for(x,y,z): 自变量x为逻辑表达式,y为执行语句,z为增量语句。当x的值为真时,依次执行表达式y和z,直到x的值为假时退出循环。 for(x,y,z)即for(判断语句x,执行语句y,增量语句z)。 该函数总是返回0值。 若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。 3.2、dowhile循环函数 dowhile(x,y): dowhile为先执行后判断的循环函数。即先执行表达式x,然后计算逻辑表达式y的值,直到y的值为假时退出循环。 dowhile(x,y)即dowhile(执行语句x,判断语句y)。 该函数总是返回0值。 若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。 3.3、判断函数 if(逻辑值x,表达式y): 当逻辑值x为真时,执行表达式y,否则,不执行表达式y。 该函数总是返回0值。 3.4、自定义分段函数 which(逻辑值1,表达式1,逻辑值2,表达式2,... ...,逻辑值n,表达式n,缺省表达式): FORCAL从前往后检测逻辑值,当检测到逻辑真时,计算与此逻辑真对应的表达式并返回该表达式的值,如果没有检测到逻辑真,则计算缺省表达式的值作为返回值,若此时没有缺省表达式,则产生一个运行错误。 例如下式定义了一个分段函数:(x)=which[gt(x,0),2*x-1,x*x-1]。 若fcerr=1:没有参数或找不到返回值。 如果舍弃该函数的返回值,则该函数可以作为一个选择计算函数使用。 3.5、计算指定序号的表达式的值 calfor(n,x1,x1,... ...): int(n)指出该表达式的序号,x1,x1,... ...为该表达式的参数。 若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。 3.6、获取指定序号的表达式的值 getfor(n): int(n)指出该表达式的序号。 若fcerr=-1:未对可接受表达式的二级函数进行设置,fcerr=1:指定的表达式不存在,fcerr=2:表达式未进行编译。
4、其他常用函数:
4.1、反正切函数 at2(x,y): 求x/y的正切值,所在象限由x和y的符号确定。 4.2、最大值函数 max(x1,x2,x3,... ...): 若fcerr=1:没有参数。 4.3、最小值函数min(x1,x2,x3,... ...): 若fcerr=1:没有参数。 4.4、余数函数 fmod(x,y): 求x/y的余数。 4.5、取小数部分函数 modf(x): 该函数把x分解成整数和小数部分,并返回小数部分。 4.6、符号传送函数 sign(x,y): 该函数的符号取y的符号,数值取x的绝对值,若y=0无符号传送,返回x值。 4.7、正差函数 dim(x,y): 当x>y时得x-y,否则返回0。 4.8、数值测试函数 testdouble(x,y,z): 该函数测试z是否在x和y之间,如果不在x和y之间,可由fcerr()函数检查到这个错误,该函数总是返回z值。 若fcerr=1:z值超出范围。 4.9、随机数发生器种子设置 srand(x): 该函数用来建立由rand()所产生的序列值的启始点,该函数总是返回0。 4.10、随机数 rand(): 该函数产生一个随机数,每调用一次,就返回一个0到RAND_MAX之间的整数,RAND_MAX的值由C++定义。 4.11、变步长辛卜生一元积分 simpintegrate(a,b,eps,n,x2,x3,... ...): a为积分下限,b为积分上限,eps为积分精度要求,int(n)指出被积函数所在的表达式序号,x2,x3,... ...表示可以向被积函数传递多个参数。 例1: 将下式编译为2号表达式:(x)=sin[x]+0.8 编译并计算0号表达式:(a,b,eps,x)=x-simpintegrate(a,b,eps,2)+... ... 该例子中没有多余的参数传递。 例2: 将下式编译为3号表达式:(x,y,z)=x+y-z 编译并计算0号表达式:(a,b,eps,x1,x2)=x1-simpintegrate(a,b,eps,3,x1,x2)+... ... 该例子中x1和x2将被传递给3号表达式的y和z。 注意:被积函数的第一个参数为积分变量,x2,x3,... ...与被积函数的其余参数要匹配; 若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:循环次数超出限制。 4.12、获取流逝过去的时钟脉冲次数 clock()。 4.13、求和函数 sum(n,m,x1,x2,... ...,xm,y1min,y1max,y1dy,y2min,y2max,y2dy... ...): int(n)指出求和函数所在的表达式序号,m指出向求和函数传递的参数个数为x1,x2,... ...,xm;y1min,y1max,y1dy为第一个自变量的初值、终值和参数增量[初值<终值,参数增量>0],依次类推。 例1: 将下式编译为2号表达式:(x,y)=sin[x]+0.8-y 编译并计算0号表达式:(a,b,dx)=2-sum(2,0,a,b,dx,2,5,0.1)+... ... 该例子中没有多余的参数传递。 例2: 将下式编译为3号表达式:(x,y,z)=x+y-z 编译并计算0号表达式:(a,b,dx)=2-sum(3,1,7,a,b,dx,2,5,0.1)+... ... 该例子中sum将7传递给3号表达式的参数z。 fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:常量表达式,无法求和;fcerr=5:内存分配失败;fcerr=6:自变量参数非法。 4.14、求积函数 pro(n,m,x1,x2,... ...,xm,y1min,y1max,y1dy,y2min,y2max,y2dy... ...): 用法请参见sum(),用于求积。 fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:常量表达式,无法求积;fcerr=5:内存分配失败;fcerr=6:自变量参数非法。 4.15、数据求和函数 datasum(n,m,x1,x2,... ...,xm,y11,y12,... ...,y21,y22,... ...): int(n)指出求和函数所在的表达式序号,m指出向求和函数传递的参数个数为x1,x2,... ...,xm;y11,y12,... ...为第一组自变量数据,依次类推。 例1: 将下式编译为2号表达式:(x,y)=x+y 编译并计算0号表达式:datasum[2,0,1,2,3,4,5,1,2,3,4,5] datasum计算结果为30,该例子中没有多余的参数传递。 例2: 将下式编译为2号表达式:(x,y,z)=x+y+z 编译并计算0号表达式:datasum[2,1,10,1,2,3,4,5,1,2,3,4,5] datasum计算结果为80,该例子中datasum将10传递给2号表达式的参数z。 若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:常量表达式,无法求和。 4.16、数据求积函数 datapro(n,m,x1,x2,... ...,xm,y11,y12,... ...,y21,y22,... ...): 用法请参见datasum(),用于数据求积。 若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:常量表达式,无法求积。 4.17、设定函数递归调用的最大次数 setstackmax(n): int(n)是1到32766之间的一个整数,函数递归调用最大次数的缺省值为16,该函数返回0。 若fcerr=1:设置错误,int(n)为非法数据;fcerr=2:内存分配错误。 4.18、零函数 zero(x): 该函数总是返回0,x通常是初始化表达式。 4.19、设定某些函数内循环的最大次数 setcyclemax(n): int(n)是2到2147483647之间的一个整数,函数内循环的最大次数的缺省值为1000000,该函数返回0,for、dowhile和simpintegrate函数将受到该参数的影响。 若fcerr=1:设置错误,int(n)为非法数据。 4.20、数组数据求和函数 dataarraysum(n,m,x1,x2,... ...,xm,nn,n1,n2,... ...): 该函数以数组中的数据为自变量,对某个表达式进行累计求和。int(n)指出求和函数所在的表达式序号,m指出可以向求和函数传递m个参数,即x1,x2,... ...,xm。nn指出有nn组数据,n1,n2,... ...为与自变量相对应的多个数组。 若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:常量表达式,无法求和;fcerr=5:数据组数int(nn)应大于0;fcerr=6:数组n1,n2,... ...中的某个数组长度小于nn。 4.21、数值测试函数 finite(x): 测试x的值是否是有限的。 若fcerr=1:x的值是无限的或为非数值数据。
----------------------------------3-----------------------------
三、实例程序及源代码[forcaltest.exe]
(一)、使用说明:
1、该程序使用简单,请参考程序运行时的说明。 2、建议先在文本编辑器例如记事本中输入数学表达式及自变量,然后将表达式及自变量复制粘贴到forcaltest.exe中,这样改写表达式较为方便。请将以下几行表达式及自变量数据逐行复制粘贴或全部复制粘贴到forcaltest.exe中,观察程序运行情况: (x,y)=x+y ? !! 0号表达式;下一行为该表达式的两个自变量; 2 3 (x)=2*x ? !! 1号表达式;下一行为该表达式的自变量; 3 simpintegrate[0,5,0.00001,1] ? !! 对1号表达式进行积分; 3、以下例子中用表达式作参数者均从0号表达式开始粘贴输入。
(二)、计算实例:
1、FORCAL与VC的速度比较:在非0号表达式中使用自定义外部函数speed[]即可进行比较。
2、for循环的用法及速度:
newdoubles(10) ? !!用newdoubles申请10个双精度数; setd[0,0]+setd[2,0] ? 将双精度数0设为0,双精度数2设为0; -clock()+ !!获得现在的时间; for{le{getd[0],1000}, !! 外for循环的逻辑表达式; setd[1,0]+for{le{getd[1],1000}, !! 外for循环的执行语句,执行内for循环; addgetd[2,sin(getd[0])+cos(getd[0]-getd[1])], !! 内for循环的执行语句; addgetd[1,1] !! 内for循环的增量语句; }, addgetd[0,1] !! 外for循环的增量语句; } +clock() ? !! 计算结果为运行时间[此语句要单独复制粘贴执行,否则运行时间不准确]; getd[2] ? !!获得双精度数2终值;
3、dowhile循环的用法及速度:
newdoubles(10) ? !!用newdoubles申请10个双精度数; setd[0,1001]+setd[2,0] ? -clock()+ dowhile{setd[1,1001]+dowhile{addgetd[2,sin(getd[0]-1)+cos(getd[0]-getd[1])], addgetd[1,-1] }, addgetd[0,-1] } +clock() ? !! 计算结果为运行时间[此语句要单独复制粘贴执行,否则运行时间不准确]; getd[2] ? !!获得双精度数2终值;
4、求和函数sum的用法:
(x,y)=cos{1-sin[1.2*[x+0.1]^(y/2-x)+cos{1-sin[1.2*[x+0.2]^(y/3-x)]}]-cos{1-sin[1.2*[x+0.3]^(y/4-x)]}-cos{1-sin[1.2*[x+0.4]^(y/5-x)+cos{1-sin[1.2*[x+0.5]^(y/6-x)]}]-cos{1-sin[1.2*[x+0.6]^(y/7-x)]}}} ? !! 0号表达式; 1 2 sum[0,0;0,1,0.0011;1,2,0.0011] ? !! 1号表达式;
5、数据求和函数datasum的用法:
f(x,y)=x+y ?!! 求和公式; 1 2 datasum[0,0,1,2,3,4,5,2,3,4,5,6] ?
说明:对于式子f(x,y)=x+y,求x,y分别取1,2、2,3、3,4、4,5、5,6时的值的和。即求f[1,2]+f[2,3]+f[3,4]+f[4,5]+f[5,6]的值。
(三)、源代码:请参见 forcaltest.cpp,在本软件的压缩包内。
=================================================================
本软件下载请到作者主页或者在csdn下载:http://www.csdn.net/cnshare/soft/11/11030.shtm 作者主页:http://wangluwanglu.yeah.net/ 或 http://forcal.jxsr.net/ E-mail:wanglu@shareware.com.cn 或 wanglu71641@sina.com 或 wangluwanglu@163.com
山东省工业学校工艺教研室(255070) 王 禄
2002.2-2002.12
|