关于FORCAL.DLL的声明
免责声明:尽管作者对FORCAL.DLL作了极为严格的测试,但仍不能保证没有丝毫错误,由于这些错误或用户判断错误造成的任何后果,本人皆不承担任何法律责任,不支付任何直接和间接的经济赔偿。如果您使用本软件或注册本软件,就默认认同了该“免责声明(disclaimer)”。特此声明。
您可以自由传播FORCAL.DLL共享版而不受任何限制,但FORCAL.DLL正式版仅供个人使用,未经授权禁止以任何形式传播FORCAL.DLL正式版。同时,对于这两个版本的动态库,您都不能仿制、解密或作其他任何形式的更改,否则将在法律许可的范围内受到最大可能的起诉。
作者仅对FORCAL.DLL拥有全部版权,由FORCAL.DLL支持的实用程序的版权归实用程序的开发者所有。
您不能将FORCAL.DLL用于任何非法用途。
FORCAL.DLL V5.1 使用说明
导读: [目录]
1、认识FORCAL.DLL:介绍FORCAL的主要功能和用法,包括FORCAL动态库的输出函数说明和主要技术指标。
2、FORCAL的二级函数:包括数据类型函数、逻辑函数、流程控制函数和一些常用数学函数等,极大地扩展了FORCAL的数值计算功能。
3、FORCAL中的字符数据处理。
4、实例程序及源代码[forcaltest.exe]:这是一个由FORCAL.DLL支持的数值计算程序,用于全面演示FORCAL的函数包括所有的二级函数以及自定义外部函数的用法。在该程序中,你可以看到如何向FORCAL添加可由FORCAL调用的外部函数。同时,该程序中的一个自定义外部函数speed()比较了FORCAL和VC的执行速度。
5、注册说明。
1 认识FORCAL.DLL 1.1 主要技术指标 1.2 FORCAL表达式 1.3 FORCAL中的代码优化 1.4 FORCAL的速度 1.5 FORCAL.DLL共享版与正式版的区别 1.6 FORCAL.DLL中的动态库函数说明 1.7 如何使用FORCAL.DLL 2 FORCAL的二级函数 2.1 实数函数 2.1.1 一个特殊的一级函数 mov(x) 2.1.2 全局变量及数组函数 2.1.3 逻辑函数 2.1.4 表达式相互调用及流程控制函数 2.1.5 其他常用函数 2.2 复数函数 2.2.1 一个特殊的一级函数 mov(x) 2.2.2 全局变量及数组函数 2.2.3 逻辑函数 2.2.4 表达式相互调用及流程控制函数 2.2.5 其他常用函数 |
2.3 整数函数 2.3.1 一个特殊的一级函数 mov(x) 2.3.2 全局变量及数组函数 2.3.3 逻辑函数 2.3.4 表达式相互调用及流程控制函数 2.3.5 其他常用函数 3 FORCAL中的字符数据处理 4 实例程序及源代码[forcaltest.exe] 4.1 使用说明 4.2 计算实例 4.3 源代码 4.4 最简单的例子 5 注册说明 |
正文:
FORCAL.DLL是一个通用的数学表达式编译计算动态库,基于FORCAL技术构建,以下将简称为FORCAL。
1.1 主要技术指标
[返回页首] [返回目录]
1、表达式最大长度:32K;
2、自变量个数:不限;
3、变量个数:不限;
4、最多可用的实数表达式:32K;
最多可用的复数表达式:32K;
最多可用的整数表达式:32K;
5、表达式中最多可用的字符串数:不限;
6、所有表达式中最多可用的字符串总数:2G;
7、自定义外部函数个数:32K;
8、for循环、dowhile循环最大循环次数:2G;
9、表达式嵌套调用最多层数:32K;
10、执行速度:若表达式中仅含有一级函数,速度约为FORTRAN(或C/C++)执行速度的50%左右;其他情况,速度稍有下降;
11、FORCAL.DLL文件大小:136K;
12、内存需求:视FORCAL运行情况而定。
1.2.1 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 为函数名,可为任意字符,或者缺省;自变量放在小括号( )内,有多个自变量时,自变量间以逗号分隔,自变量由英文字母a...z、A...Z、下划线_和数字0...9组成,但第一个字符不能为数字,自变量个数可以为零;等号后为函数式,不可缺省。
格式2和格式3是等效的,均表示无参函数。
格式4:数学表达式的可优化表示形式。aa、bb为后置变量[在表达式后面定义,后置变量必须赋一个值],其命名方式与自变量相同且不能与任何一个自变量同名。该格式的计算顺序为从右向左,即:先计算bb,然后计算aa,最后计算F(x,y)并把该值作为整个表达式的值。
格式5表示可以将表达式放在一对括号( )、[ ]或{ }内。
函数式中的运算符有加号'+'、减号'-'、乘号'*'、除号'/'和乘方'^'五种。注意数字与自变量相乘时,乘号不可省略;在进行乘方运算时,底数应为非负数。函数式中可以用三对括号( )、[ ]和{ }。
FORCAL表达式有实数表达式、复数表达式和整数表达式三种。表达式中的函数均分为一级函数和二级函数,其中一级函数为单变量函数,运算速度较快,而二级函数功能较为丰富,非常容易扩充。
实数表达式中可以使用的基本函数如下:
一级函数:平方根sqrt,指数函数exp,常用对数lg,自然对数ln,正弦sin,余弦cos,正切tan,反正弦asin,反余弦acos,反正切atan,双曲正弦sinh,双曲余弦cosh,双曲正切tanh,取整函数int,绝对值abs,数值传送函数mov(用法见说明的第二部分)。
二级函数:请参见说明的第二部分2.1。这些二级函数包括数据类型函数、逻辑函数、流程控制函数和一些常用数学函数等,极大地扩展了FORCAL的数值计算功能。
复数表达式中可以使用的基本函数如下:
一级函数:平方根sqrt,指数函数exp,自然对数ln,正弦sin,余弦cos,取整函数int,绝对值abs,共轭函数con,实部虚部交换函数xy,实部为0函数x0,虚部为0函数y0,数值传送函数mov。
二级函数:请参见说明的第二部分2.2。
复数举例:2+3i。
复数表达式举例:F(x,y,... ...)=2+3i-sin[x-i]*ln[y]- ... ... 。
在复数表达式中不能使用 i 作为自变量,因为 i 已经用来表示虚数。
整数表达式中可以使用的基本函数如下:
一级函数:平方根sqrt,指数函数exp,常用对数lg,自然对数ln,绝对值abs,数值传送函数mov。
二级函数:请参见说明的第二部分2.3。
注意:若整数表达式中有实数,在编译时将全部转化为整数,同时在进行乘方运算以及一级函数运算时,将把整数转化为双精度实数后进行运算,最后再把运算结果转化为整数。
1.3.2 FORCAL表达式的特殊形式
FORCAL表达式的特殊形式提供了与高级语言中的函数或过程相类似的功能。
格式6:f(x,y:a,b)=one
{a=2,
b=3+a,
return[x+y+a+b]
}
在(x,y:a,b)中,冒号前的x,y为表达式的自变量参数,冒号后的a,b为在该表达式中定义的变量,由于这些变量在表达式的开头定义,故称为前置变量,同时把在表达式结尾定义的变量[见格式4]称为后置变量。自变量、前置变量和后置变量统称为变量,变量在表达式中可以重新赋值。
变量赋值的格式如下:
(a=2+3)
即要把赋值表达式放在一对括号内,同时该赋值表达式返回赋值后的变量的值。如果赋值表达式作为一个函数的参数,可以不加括号,例如格式6中的例子。
除了用赋值表达式可以给变量赋值,用数值传送函数mov[x]也可以给变量赋值,并且,对于下列表达式,mov函数比赋值表达式的执行速度更快:
[x=x+f(...)]
mov[f(...)+x]
另外,例子中的one[...]是一个多变量函数,该函数总是返回0值;return[x]函数返回表达式的值为x。
以下例子能帮助您进一步了解FORCAL表达式的格式:
(1)、(:x,y)=[x=2]+[y=x+3]
无参表达式,但该表达式使用了两个前置变量x和y,该表达式的值为7。
(2)、(x,y:)=[x=2]+[y=x+3]
该表达式有两个自变量参数x和y,但该表达式的值总是7。
(3)、(:)=2+3
无参表达式,该表达式与2+3等效。
(4)、f(x,y:a,b)=one
{a=2,
b=3+a,
return[x+y+a+b+c+d]
},c=8,d=9
该表达式有两个自变量参数x和y,同时使用了两个前置变量a和b,使用了两个后置变量c和d。
最后指出,(1)、在FORCAL表达式中英文字母不区分大小写(字符串"..."中的字符除外),(2)、FORCAL表达式中的空格字符将被忽略(字符串"..."中的空格字符除外)。例如,变量ab2、a B2和Ab2是一样的。
1.3 FORCAL中的代码优化 [返回页首] [返回目录]
FORCAL编译器在编译表达式时能进行两种形式的代码优化,其一是预先计算表达式中可以计算的部分,其二是采用格式4表示的数学表达式的可优化形式。
FORCAL将最大限度地进行第一种代码优化,但这种自动进行的优化并不彻底,若要获得最优化的代码,您需要将表达式中可以计算的部分用括号括起来(一般情况下不需要这样做)。
例如:要想进行彻底的第一种代码优化,需要将式子:
F(x,y)=x-5-7+y
写成:F(x,y)=x-[5+7]+y或F(x,y)=x+[-5-7]+y
需要注意的是,在进行第一种代码优化时,只有一级函数(mov()函数除外)可以进行预先计算,二级函数的计算始终只能在编译后的表达式中进行。
FORCAL的第二种代码优化可以保证表达式中的任何相同部分只进行一次计算,从而最大限度地提高了计算速度。
1.4 FORCAL的速度
[返回页首] [返回目录]
FORCAL是由C/C++的编译程序生成的,所以它的速度要稍慢些,若表达式中仅含有一级函数,速度约为FORTRAN(或C/C++)执行速度的50%左右,其他情况,速度稍有下降。
1.5 FORCAL.DLL共享版与正式版的区别
[返回页首] [返回目录]
在共享版中FORCAL编译表达式的长度受到一定限制,除此之外,共享版与正式版没有任何区别。在一般的计算中,共享版是完全可以胜任的。但如果要使用很长的式子,则需要注册FORCAL.DLL正式版。正式版中最多允许使用长达32766个字符的数学表达式。
注意:您不能将您的软件连同FORCAL.DLL正式版一起发布,因为FORCAL.DLL正式版仅供个人使用。
1.6 FORCAL.DLL中的动态库函数说明
[返回页首] [返回目录]
(1)、版本信息函数:const char *ver(void) [序列号:1]。
(2)、表达式个数设置函数:bool setfornum(int m) [序列号:2]:
设置FORCAL.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:表达式中的字符串无效,即"..."不匹配或者转义字符错误;
19:没有启用forcal的字符串处理功能;
20:表达式中的字符串太多或表达式太长;
21:内存分配失败;
22:找不到字符串$"..."所表示的表达式的类型;
23:找不到字符串#"..."所表示的表达式的序号;
24:找不到字符串&"..."的地址;
25:字符串数组不够用,需重新设置;
26:超出共享版允许的字符限制,请注册使用正式版。[在正式版中无此返回值]
(4)、计算表达式的值:double rcal(int m,double a[]) [序列号:4]:
计算第m个表达式的值,数组a中依次存放自变量。
(5)、设置常量:void setdoubleconst(char **strs,double *dconst)
[序列号:5]。
设置编译表达式时可能用到的常量。字符串表指针strs指出常量名(由英文小写字母a...z、下划线_和数字0...9组成,但第一个字符不能为数字,注意不能使用英文大写字母A...Z),串表的最后应是一个空名,表示该串表的结束;常量数组dconst与strs相对应。如果常量名与自变量名相同,则忽略这个常量。
例如:
char *strs[]={"pi","ee","_111_",""}; //定义了三个常量;
double dconst[]={3.14,2.718,111.0}; //设置常量的值;
setdoubleconst(strs,dconst); //设置常量;
(6)、动态库错误函数:int fcerr(char *&errname) [序列号:6]:
该函数在使用rcal或rcals函数后调用,返回动态库的第一个运行错误,fcerr返回错误类型,errname返回出错函数名,该函数被调用后,将把错误类型重新设置为0。
通常,可以在主程序中用int matherr(struct _exception *err)检测标准数学错误,用int fcerr(*&)检测FORCAL运行错误。
(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指出外部函数名(由英文小写字母a...z、下划线_和数字0...9组成,但第一个字符不能为数字,同时不能用单个英文小写字母作外部函数名,不能使用英文大写字母A...Z),串表的最后应是一个空名,表示该串表的结束;整数数组n的对应项存放每个函数的自变量个数,其中-2表示有不确定的多个自变量,-1表示有0个自变量,0表示有1个自变量,依次类推;指向函数指针数组的指针fun指出每一个对应的函数,每个函数有两个相同的变量,其中dd为一个存放自变量的双精度数组,k为该数组的长度-1。
设置成功函数返回true,否则返回false。
例如:
char *pch[]={"asd","aa2a",""}; //asd和aa2a为两个函数名;
int n[]={1,0}; //1表示有2个自变量,0表示有1个自变量;
double (*fun[])(int ,double *)={asd,aa2a}; //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]:
该数组记录了各个表达式的自变量个数。
以下(17)~(32)函数使用_stdcall修饰符输出,可以在VB、delphi等高级语言中使用,用法参见(1)~(16)函数:
(17)、const char * _stdcall STDver(void); [序列号:17]
(18)、bool _stdcall STDsetfornum(int); [序列号:18]
(19)、void _stdcall STDsetdoubleconst(char **,double *); [序列号: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]
以下(33)~(47)和(48)~(62)函数将使您能使用复数表达式,用法请参见(2)~(16)和(18)~(32)函数:
(33)、bool Csetfornum(int); [序列号:33]
(34)、void Csetcomplexconst(char **,_complex *); [序列号:34]
(35)、int Ccom(int ,char [],int &); [序列号:35]
(36)、_complex Ccal(int ,_complex []); [序列号:36]
(37)、_complex * Cgetin(int ); [序列号:37]
(38)、_complex Ccals(int ); [序列号:38]
(39)、_complex * Cgetfccomplexs(long &); [序列号:39]
(40)、_complex ** Cgetfccomplexarrays(long &,long *&); [序列号:40]
(41)、bool Csetfcfun(char **,int *,_complex (**)(int ,_complex *)); [序列号:41]
(42)、_complex ** Cgetallin(void); [序列号:42]
(43)、bool * Cgetfortrue(void); [序列号:43]
(44)、int * Cgetvarnum(void); [序列号:44]
(45)、int Cfcerr(char *&); [序列号:45]
(46)、int Cfcerrnum(void); [序列号:46]
(47)、void Csetfcerr(int ,char *); [序列号:47]
(48)、bool _stdcall STDCsetfornum(int); [序列号:48]
(49)、void _stdcall STDCsetcomplexconst(char **,_complex *); [序列号:49]
(50)、int _stdcall STDCcom(int ,char [],int &); [序列号:50]
(51)、_complex _stdcall STDCcal(int ,_complex []); [序列号:51]
(52)、_complex * _stdcall STDCgetin(int ); [序列号:52]
(53)、_complex _stdcall STDCcals(int ); [序列号:53]
(54)、_complex * _stdcall STDCgetfccomplexs(long &); [序列号:54]
(55)、_complex ** _stdcall STDCgetfccomplexarrays(long &,long *&); [序列号:55]
(56)、bool _stdcall STDCsetfcfun(char **,int *,_complex
(**)(int ,_complex *)); [序列号:56]
(57)、_complex ** _stdcall STDCgetallin(void); [序列号:57]
(58)、bool * _stdcall STDCgetfortrue(void); [序列号:58]
(59)、int * _stdcall STDCgetvarnum(void); [序列号:59]
(60)、int _stdcall STDCfcerr(char *&); [序列号:60]
(61)、int _stdcall STDCfcerrnum(void); [序列号:61]
(62)、void _stdcall STDCsetfcerr(int ,char *); [序列号:62]
以下(63)~(77)和(78)~(92)函数将使您能使用整数表达式,用法请参见(2)~(16)和(18)~(32)函数:
(63)、bool Isetfornum(int); [序列号:63]
(64)、void Isetlongconst(char **,long *); [序列号:64]
(65)、int Icom(int ,char [],int &); [序列号:65]
(66)、long Ical(int ,long []); [序列号:66]
(67)、long * Igetin(int ); [序列号:67]
(68)、long Icals(int ); [序列号:68]
(69)、long * Igetfclongs(long &); [序列号:69]
(70)、long ** Igetfclongarrays(long &,long *&); [序列号:70]
(71)、bool Isetfcfun(char **,int *,long (**)(int ,long *)); [序列号:71]
(72)、long ** Igetallin(void); [序列号:72]
(73)、bool * Igetfortrue(void); [序列号:73]
(74)、int * Igetvarnum(void); [序列号:74]
(75)、int Ifcerr(char *&); [序列号:75]
(76)、int Ifcerrnum(void); [序列号:76]
(77)、void Isetfcerr(int ,char *); [序列号:77]
(78)、bool _stdcall STDIsetfornum(int); [序列号:78]
(79)、void _stdcall STDIsetlongconst(char **,long *); [序列号:79]
(80)、int _stdcall STDIcom(int ,char [],int &); [序列号:80]
(81)、long _stdcall STDIcal(int ,long []); [序列号:81]
(82)、long * _stdcall STDIgetin(int ); [序列号:82]
(83)、long _stdcall STDIcals(int ); [序列号:83]
(84)、long * _stdcall STDIgetfclongs(long &); [序列号:84]
(85)、long ** _stdcall STDIgetfclongarrays(long &,long *&); [序列号:85]
(86)、bool _stdcall STDIsetfcfun(char **,int *,long (**)(int
,long *)); [序列号:86]
(87)、long ** _stdcall STDIgetallin(void); [序列号:87]
(88)、bool * _stdcall STDIgetfortrue(void); [序列号:88]
(89)、int * _stdcall STDIgetvarnum(void); [序列号:89]
(90)、int _stdcall STDIfcerr(char *&); [序列号:90]
(91)、int _stdcall STDIfcerrnum(void); [序列号:91]
(92)、void _stdcall STDIsetfcerr(int ,char *); [序列号:92]
(93)、使实数、复数和整数表达式可以相互调用:void userci(void); [序列号:93]
该函数在setfornum(int)、Csetfornum(int)和Isetfornum(int)后使用。
(94)、使实数、复数和整数表达式可以相互调用:void STDuserci(void); [序列号:94]
userci函数的_stdcall修饰符输出,用法同userci。
(95)、释放动态库所申请的全部空间:void deletedll(void); [序列号:95]
(96)、释放动态库所申请的全部空间:void STDdeletedll(void); [序列号:96]
deletedll函数的_stdcall修饰符输出,用法同deletedll。
(97)、设置forcal所用的字符串最大数目:bool setfcstrmax(long
n); [序列号:97]
设置forcal所用的字符串最大值,n<10时将删除字符串空间;
(98)、设置forcal所用的字符串最大数目:bool _stdcall STDsetfcstrmax(long ); [序列号:98]
请参考setfcstrmax的说明。
(99)、获得forcal的字符串数组指针,同时获得存放每个子串长度的长整型数组指针:char **getfcstr(long *& ); [序列号:99]
(100)、获得forcal的字符串数组指针,同时获得存放每个子串长度的长整型数组指针:char ** _stdcall STDgetfcstr(long *& ); [序列号:100]
(101)、初始化字符串空间:void initfcstr(void); [序列号:101]
(102)、初始化字符串空间:void _stdcall STDinitfcstr(void); [序列号:102]
1.7 如何使用FORCAL.DLL
[返回页首] [返回目录]
1.7.1使用FORCAL进行简单的实数计算
1、用setfornum(int m)设置m个可用的实数表达式;
2、用rcom(int m,char a[],int &n)编译第m个表达式;
3、用rcal(int m,double a[])或者rcals(int m)计算第m个表达式;
4、用deletedll(void)释放动态库所申请的空间。
1.7.2 使用FORCAL进行简单的复数计算
1、用Csetfornum(int m)设置m个可用的实数表达式;
2、用Ccom(int m,char a[],int &n)编译第m个表达式;
3、用Ccal(int m,_complex a[])或者Ccals(int m)计算第m个表达式;
4、用deletedll(void)释放动态库所申请的空间。
1.7.3 使用FORCAL进行简单的整数计算
1、用Isetfornum(int m)设置m个可用的实数表达式;
2、用Icom(int m,char a[],int &n)编译第m个表达式;
3、用Ical(int m,long a[])或者Icals(int m)计算第m个表达式;
4、用deletedll(void)释放动态库所申请的空间。
1.7.4 使用FORCAL进行简单的实数、整数和复数计算
1、设置表达式
用setfornum(int m)设置m个可用的实数表达式;
用Csetfornum(int m)设置m个可用的实数表达式;
用Isetfornum(int m)设置m个可用的实数表达式。
2、用userci(void)使实数、复数和整数表达式可以相互调用
3、编译表达式
用rcom(int m,char a[],int &n)编译第m个表达式;
用Ccom(int m,char a[],int &n)编译第m个表达式;
用Icom(int m,char a[],int &n)编译第m个表达式。
4、计算表达式
用rcal(int m,double a[])或者rcals(int m)计算第m个表达式;
用Ccal(int m,_complex a[])或者Ccals(int m)计算第m个表达式;
用Ical(int m,long a[])或者Icals(int m)计算第m个表达式。
5、用deletedll(void)释放动态库所申请的空间
1.7.5 使用自定义外部函数
使用setfcfun、Csetfcfun和Isetfcfun可以设置可由FORCAL调用的实数、复数和整数外部函数。
可在deletedll(void)之前的任意位置使用这三个函数,但一般在程序开头使用。
1.7.6 FORCAL外部函数设计
以设计实数外部函数为例进行说明,复数、整数的外部函数设计与此类似,不再赘述。
外部函数设计中可能用到以下各项:
1、自变量数组指针:由*getin(int m)获得;
2、存放各表达式的自变量的指针数组的指针:由**getallin(void)获得;
3、表示表达式是否编译成功的数组的指针:由*getfortrue(void)获得;
4、存放各个表达式的自变量的个数的整数数组的指针:由*getvarnum(void)获得;
以上函数需在setfornum(int m)、Csetfornum(int m)和Isetfornum(int m)后使用,但可用全局变量保存这些指针值,以便在设计外部函数时使用。
5、一维存储数组double的指针:由*getfcdoubles(long &n)获得;
6、多维存储数组doublearray的指针:由**getfcdoublearrays(long &n,long *&m)获得;
7、用fcerr(char *&errname)获取FORCAL运行错误;
8、用setfcerr(int n,char *ch)设置外部函数的运行错误;
9、用fcerrnum(void)获得动态库运行错误的类型;
函数5~9需在外部函数体内使用。
1.7.7 使用FORCAL字符串
1、用setfcstrmax(long )设置字符串的最大数目;
2、用**getfcstr(long *& )获得字符串数组的指针,同时获得存放每个子串长度的长整型数组指针;
3、用initfcstr(void)初始化字符串空间,该函数使用后,以前使用的字符串将不再保留。
1.7.8 使用FORCAL常量
用setdoubleconst(char **strs,double *dconst)函数设置在实数表达式中可能用到的常量。复数和整数表达式中的常量设置与此类似。
说明:
在以下说明中,fcerr为动态库函数运行错误代码,int(m)表示取实数m的整数部分。
FORCAL可设置同时使用多个表达式,假如设置了n个表达式,则表达式的序号分别为0、1、2、...、 i、 ...、n-1,第i个表达式简称为表达式i。
部分函数的举例请参见本文第四部分:实例程序及源代码[forcaltest.exe]。
2.1.1 一个特殊的一级函数 mov(x)
[返回页首] [返回目录]
mov(x)函数将x值传送至最近使用的一个变量,因此对该变量进行了重新赋值。注意该函数实际上有两个参数,源参数为x,但目的参数即“最近使用的一个变量”却是隐含的。“最近使用的一个变量”即按照表达式的计算顺序,在mov函数执行之前最后使用的变量。详见下面的例子:
例1:(x)=x+mov[5]+x 当x为2时表达式的值为12而不是9。
例2:(x)=x+mov[x+5]+x 当x为2时表达式的值为16。
例3:(a,b,c)=one(a,mov[5],b,mov[8],mov[a+b+(c-c)],mov[a+b]) 不论计算开始时a,b,c为何值,计算结束时a为5,b为13,c为13,可以用para(n,m)函数(详见para的介绍)获取这些自变量参数。
2.1.2 全局变量及数组函数
[返回页首] [返回目录]
2.1.2.1 设置多个双精度实数变量 NewDoubleS(m)
该函数设置int(m)个双精度实数,若int(m)<1,则删除这些双精度实数,该函数总是返回0。
这些双精度实数从0开始编号,即:0,1,2,3,... ...,m-1。
若fcerr=1,设置失败。
以下这些函数可以对这些双精度实数进行各种运算操作。
1、对一个双精度实数进行赋值 setd(n,x)
将第int(n)个双精度实数的值设为x,该函数返回x的值。
若fcerr=1,表示不存在第int(n)个双精度实数。
2、获得一个双精度实数的值 getd(n)
获得第int(n)个双精度实数的值。
若fcerr=1,表示不存在第int(n)个双精度实数。
3、将一个数加到一个双精度实数上并返回相加后的值 addgetd(n,x)
先将x加到第int(n)个双精度实数上,然后返回相加后的值。
若fcerr=1,表示不存在第int(n)个双精度实数。
4、获得一个双精度实数的值后再将另一个数加到该双精度实数上 getdadd(n,x)
该函数先返回第int(n)个双精度实数的值,然后将x加到第int(n)个双精度实数上。
若fcerr=1,表示不存在第int(n)个双精度实数。
2.1.2.2 设置多个一维双精度实数数组
NewDoubleArrayS(m)
该函数设置int(m)个一维双精度实数数组,若int(m)<1,则删除这些双精度实数数组,该函数总是返回0。
这些双精度实数数组从0开始编号,即:0,1,2,3,... ...,m-1。
若fcerr=1,设置失败。
以下这些函数可以对这些双精度实数数组或数组元素进行各种运算操作。
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。
2、对一个数组元素进行赋值 setda(n,m,x)
该函数将x值存储到第int(n)个数组的第int[m]个元素位置并返回x的值。
若fcerr=1:未设置多个一维双精度实数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。
3、获得一个数组元素的值 getda(n,m)
该函数获得第int(n)个数组的第int[m]个数组元素的值。
若fcerr=1:未设置多个一维双精度实数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。
4、将一个数加到一个数组元素上并返回相加后的值 addgetda(n,m,x)
先将x加到第int(n)个数组的第int[m]个数组元素上,然后返回相加后的值。
若fcerr=1:未设置多个一维双精度实数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。
2.1.3 逻辑函数
[返回页首] [返回目录]
FORCAL用大于0的数表示逻辑真,小于等于0的数表示逻辑假。
1、gt(x,y):如果x>y返回1,否则返回-1。
2、ge(x,y):如果x>=y返回1,否则返回-1。
3、lt(x,y):如果x<y返回1,否则返回-1。
4、le(x,y):如果x<=y返回1,否则返回-1。
5、eq(x,y):如果x==y返回1,否则返回-1。
6、ne(x,y):如果x!=y返回1,否则返回-1。
7、and(x,y):如果x>0同时y>0返回1,否则返回-1。
8、or(x,y):如果x<0同时y<0返回-1,否则返回1。
9、not(x):如果x>0返回-1,否则返回1。
10、xor(x,y):如果x和y符号相同返回-1,否则返回1。
2.1.4 表达式相互调用及流程控制函数
[返回页首] [返回目录]
1、for循环函数 for(x,y1,y2,...,break(),...,continue(), ...,z)
自变量x为逻辑表达式,y1,y2,...,break(),...,continue(), ...为执行语句,z为增量语句。当x的值为真时,依次执行这些表达式,直到x的值为假时退出循环。当执行到break()函数时,跳出for循环,执行for循环后面的函数;当执行到continue()函数时,返回到for循环的开始语句x处继续执行。
for(x,y1,y2,...,break(),...,continue(), ...,z)即for(判断语句x,多个执行语句y1,y2,...,break(),...,continue(), ...,增量语句z)。
该函数至少要有2个自变量参数,其中第一个参数为逻辑表达式。
该函数总是返回0值。
若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。
该函数中continue()的使用会导致fcerr=1:循环次数超出限制。
2、dowhile循环函数 dowhile(x1,x2,...,break(),...,continue(),...,y)
dowhile为先执行后判断的循环函数。即先执行多个表达式x1,x2,...,break(),...,continue(),...,然后计算逻辑表达式y的值,直到y的值为假时退出循环。当执行到break()函数时,跳出dowhile循环,执行dowhile循环后面的函数;当执行到continue()函数时,返回到dowhile循环的开始语句x1处继续执行。
dowhile(x1,x2,...,break(),...,continue(),...,y)即dowhile(多个执行语句x1,x2,...,break(),...,continue(),...,判断语句y)。
该函数至少要有2个自变量参数,其中最后一个参数为逻辑表达式。
该函数总是返回0值。
若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。
该函数中continue()的使用会导致fcerr=1:循环次数超出限制。
3、判断函数 if(x,y1,y2,... ...,yn)
当逻辑值x为真时,依次执行表达式y1,y2,... ...,yn,否则,不执行表达式y1,y2,... ...,yn。
该函数至少要有2个自变量参数,其中第一个参数为逻辑表达式。
该函数总是返回0值。
4、自定义分段函数 which(逻辑值1,表达式1,逻辑值2,表达式2,... ...,逻辑值n,表达式n,缺省表达式)
FORCAL从前往后检测逻辑值,当检测到逻辑真时,计算与此逻辑真对应的表达式并返回该表达式的值,如果没有检测到逻辑真,则计算缺省表达式的值作为返回值,若此时没有缺省表达式,则产生一个运行错误。
例如下式定义了一个分段函数:(x)=which[gt(x,0),2*x-1,x*x-1]。
若fcerr=1:没有参数或找不到返回值。
如果舍弃该函数的返回值,则该函数可以作为一个选择计算函数使用。
5、计算指定序号的表达式的值 calfor(n,x1,x2,... ...)
int(n)指出该表达式的序号,x1,x2,... ...为该表达式的参数。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
6、获取表达式的自变量参数的值 para(n,m)
int(n)指出该表达式的序号,int(m)指出自变量参数的序号。
若fcerr=-1:未对可接受表达式的二级函数进行设置,fcerr=1:指定的表达式不存在,fcerr=2:表达式未进行编译,fcerr=3:指定的自变量参数不存在。
7、计算指定序号的复数表达式的值 calcfor(n,x1,y1,x2,y2,... ...)
int(n)指出该表达式的序号,x1,y1,x2,y2,... ...为该表达式的参数,其中xi为复数的实部,yi为复数的虚部。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
8、计算指定序号的整数表达式的值 califor(n,x1,x2,... ...)
int(n)指出该表达式的序号,x1,x2,... ...为该表达式的参数。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
9、合并表达式函数one(x1,x2,... ...,xn)
该函数可将多个无参表达式合并为一个表达式,以减少表达式个数,节约内存,并可提高执行速度。
该函数总是返回0值。
10、return返回函数 return(x)
结束计算并返回表达式的值为x。
2.1.5 其他常用函数
[返回页首] [返回目录]
1、反正切函数 at2(x,y):
求x/y的正切值,所在象限由x和y的符号确定。
2、最大值函数 max(x1,x2,x3,... ...):
若fcerr=1:没有参数。
3、最小值函数min(x1,x2,x3,... ...):
若fcerr=1:没有参数。
4、余数函数 fmod(x,y):
求x/y的余数。
5、取小数部分函数 modf(x):
该函数把x分解成整数和小数部分,并返回小数部分。
6、符号传送函数 sign(x,y):
该函数的符号取y的符号,数值取x的绝对值,若y=0无符号传送,返回x值。
7、正差函数 dim(x,y):
当x>y时得x-y,否则返回0。
8、变步长辛卜生一元积分 simpintegrate(a,b,eps,n,x2,x3,... ...):
a为积分下限,b为积分上限,eps为积分精度要求,int(n)指出被积函数所在的表达式序号,x2,x3,... ...表示可以向被积函数传递多个参数。
例1:
将下式编译为2号表达式:(x)=sin[x]+0.8
编译并计算2号表达式:(a,b,eps,x)=x-simpintegrate(a,b,eps,2)+... ...
该例子中没有多余的参数传递。
例2:
将下式编译为3号表达式:(x,y,z)=x+y-z
编译并计算3号表达式:(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:循环次数超出限制。
9、求和函数 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
编译并计算2号表达式:(a,b,dx)=2-sum(2,0,a,b,dx,2,5,0.1)+... ...
该例子中没有多余的参数传递。
例2:
将下式编译为3号表达式:(x,y,z)=x+y-z
编译并计算3号表达式:(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:自变量参数非法。
10、求积函数 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:自变量参数非法。
11、数据求和函数 datasum(n,m,x1,x2,... ...,xm,y11,y12,... ...,y21,y22,... ...):
int(n)指出求和函数所在的表达式序号,m指出向求和函数传递的参数个数为x1,x2,... ...,xm;y11,y12,... ...为第一组自变量数据,依次类推。
例1:
将下式编译为2号表达式:(x,y)=x+y
编译并计算2号表达式:datasum[2,0,1,2,3,4,5,1,2,3,4,5]
datasum计算结果为30,该例子中没有多余的参数传递。
例2:
将下式编译为2号表达式:(x,y,z)=x+y+z
编译并计算2号表达式: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:常量表达式,无法求和。
12、数据求积函数 datapro(n,m,x1,x2,... ...,xm,y11,y12,... ...,y21,y22,... ...):
用法请参见datasum(),用于数据求积。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配;fcerr=4:常量表达式,无法求积。
13、设定函数递归调用的最大次数 setstackmax(n):
int(n)是1到32766之间的一个整数,函数递归调用最大次数的缺省值为16,该函数返回0。
若fcerr=1:设置错误,int(n)为非法数据;fcerr=2:内存分配错误。
14、设定某些函数内循环的最大次数 setcyclemax(n):
int(n)是2到2147483647之间的一个整数,函数内循环的最大次数的缺省值为1000000,该函数返回0,for、dowhile和simpintegrate函数将受到该参数的影响。
若fcerr=1:设置错误,int(n)为非法数据。
15、数组数据求和函数 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。
说明:
在以下说明中,fcerr为动态库函数运行错误代码,int(m)表示取复数m的实部的整数部分。
FORCAL可设置同时使用多个表达式,假如设置了n个表达式,则表达式的序号分别为0、1、2、...、 i、 ...、n-1,第i个表达式简称为表达式i。
2.2.1 一个特殊的一级函数 mov(x)
[返回页首] [返回目录]
mov(x)函数将x值传送至最近使用的一个变量,因此对该变量进行了重新赋值。注意该函数实际上有两个参数,源参数为x,但目的参数即“最近使用的一个变量”却是隐含的。“最近使用的一个变量”即按照表达式的计算顺序,在mov函数执行之前最后使用的变量。详见下面的例子:
例1:c(x)=x+mov[5+6i]+x 当x为2+3i时表达式的值为12+15i而不是9+12i。
例2:c(x)=x+mov[x+5+6i]+x 当x为2+3i时表达式的值为16+21i。
例3:c(a,b,c)=one(a,mov[5+6i],b,mov[8+9i],mov[a+b+(c-c)],mov[a+b]) 不论计算开始时a,b,c为何值,计算结束时a为5+6i,b为13+15i,c为13+15i,可以用para(n,m)函数(详见para的介绍)获取这些自变量参数。
2.2.2 全局变量及数组函数
[返回页首] [返回目录]
2.2.2.1、设置多个双精度复数变量 newcomplexs(m)
该函数设置int(m)个双精度复数,若int(m)<1,则删除这些双精度复数,该函数总是返回0。
这些双精度复数从0开始编号,即:0,1,2,3,... ...,m-1。
若fcerr=1,设置失败。
以下这些函数可以对这些双精度复数进行各种运算操作。
1、对一个双精度复数进行赋值 setc(n,x):
将第int(n)个双精度复数的值设为x,该函数返回x的值。
若fcerr=1,表示不存在第int(n)个双精度复数。
2、获得一个双精度复数的值 getc(n):
获得第int(n)个双精度复数的值。
若fcerr=1,表示不存在第int(n)个双精度复数。
3、将一个数加到一个双精度复数上并返回相加后的值 addgetc(n,x):
先将x加到第int(n)个双精度复数上,然后返回相加后的值。
若fcerr=1,表示不存在第int(n)个双精度复数。
4、获得一个双精度复数的值后再将另一个数加到该双精度复数上 getcadd(n,x):
该函数先返回第int(n)个双精度复数的值,然后将x加到第int(n)个双精度复数上。
若fcerr=1,表示不存在第int(n)个双精度复数。
2.2.2.2 设置多个一维双精度复数数组 newcomplexarrays(m)
该函数设置int(m)个一维双精度复数数组,若int(m)<1,则删除这些双精度复数数组,该函数总是返回0。
这些双精度复数数组从0开始编号,即:0,1,2,3,... ...,m-1。
若fcerr=1,设置失败。
以下这些函数可以对这些双精度复数数组或数组元素进行各种运算操作。
1、设置一维双精度复数数组的长度 newcomplexarray(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。
2、对一个数组元素进行赋值 setca(n,m,x):
该函数将x值存储到第int(n)个数组的第int[m]个元素位置并返回x的值。
若fcerr=1:未设置多个一维双精度复数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。
3、获得一个数组元素的值 getca(n,m):
该函数获得第int(n)个数组的第int[m]个数组元素的值。
若fcerr=1:未设置多个一维双精度复数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。
4、将一个数加到一个数组元素上并返回相加后的值 addgetca(n,m,x):
先将x加到第int(n)个数组的第int[m]个数组元素上,然后返回相加后的值。
若fcerr=1:未设置多个一维双精度复数数组;fcerr=2:不存在第int(n)个双精度数组;fcerr=3:未对该数组进行设置或不存在第int(m)个数组元素。
2.2.3 逻辑函数
[返回页首] [返回目录]
FORCAL用实部大于0的复数表示逻辑真,实部小于等于0的复数表示逻辑假。在表示逻辑值的复数中,其虚部没有意义。
以下逻辑函数中复数x和y的比较,均比较其实部。
1、gt(x,y):如果x>y返回1,否则返回-1。
2、ge(x,y):如果x>=y返回1,否则返回-1。
3、lt(x,y):如果x<y返回1,否则返回-1。
4、le(x,y):如果x<=y返回1,否则返回-1。
5、eq(x,y):如果x==y返回1,否则返回-1。
6、ne(x,y):如果x!=y返回1,否则返回-1。
7、and(x,y):如果x>0同时y>0返回1,否则返回-1。
8、or(x,y):如果x<0同时y<0返回-1,否则返回1。
9、not(x):如果x>0返回-1,否则返回1。
10、xor(x,y):如果x和y符号相同返回-1,否则返回1。
2.2.4 表达式相互调用及流程控制函数
[返回页首] [返回目录]
1、for循环函数 for(x,y1,y2,...,break(),...,continue(), ...,z)
自变量x为逻辑表达式,y1,y2,...,break(),...,continue(), ...为执行语句,z为增量语句。当x的值为真时,依次执行这些表达式,直到x的值为假时退出循环。当执行到break()函数时,跳出for循环,执行for循环后面的函数;当执行到continue()函数时,返回到for循环的开始语句x处继续执行。
for(x,y1,y2,...,break(),...,continue(), ...,z)即for(判断语句x,多个执行语句y1,y2,...,break(),...,continue(), ...,增量语句z)。
该函数至少要有2个自变量参数,其中第一个参数为逻辑表达式。
该函数总是返回0值。
若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。
该函数中continue()的使用会导致fcerr=1:循环次数超出限制。
2、dowhile循环函数 dowhile(x1,x2,...,break(),...,continue(),...,y)
dowhile为先执行后判断的循环函数。即先执行多个表达式x1,x2,...,break(),...,continue(),...,然后计算逻辑表达式y的值,直到y的值为假时退出循环。当执行到break()函数时,跳出dowhile循环,执行dowhile循环后面的函数;当执行到continue()函数时,返回到dowhile循环的开始语句x1处继续执行。
dowhile(x1,x2,...,break(),...,continue(),...,y)即dowhile(多个执行语句x1,x2,...,break(),...,continue(),...,判断语句y)。
该函数至少要有2个自变量参数,其中最后一个参数为逻辑表达式。
该函数总是返回0值。
若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。
该函数中continue()的使用会导致fcerr=1:循环次数超出限制。
3、判断函数 if(x,y1,y2,... ...,yn)
当逻辑值x为真时,依次执行表达式y1,y2,... ...,yn,否则,不执行表达式y1,y2,... ...,yn。
该函数至少要有2个自变量参数,其中第一个参数为逻辑表达式。
该函数总是返回0值。
4、自定义分段函数 which(逻辑值1,表达式1,逻辑值2,表达式2,... ...,逻辑值n,表达式n,缺省表达式)
FORCAL从前往后检测逻辑值,当检测到逻辑真时,计算与此逻辑真对应的表达式并返回该表达式的值,如果没有检测到逻辑真,则计算缺省表达式的值作为返回值,若此时没有缺省表达式,则产生一个运行错误。
例如下式定义了一个分段函数:(x)=which[gt(x,0),2*x-1,x*x-1]。
若fcerr=1:没有参数或找不到返回值。
如果舍弃该函数的返回值,则该函数可以作为一个选择计算函数使用。
5、计算指定序号的表达式的值 calfor(n,x1,x2,... ...)
int(n)指出该表达式的序号,x1,x2,... ...为该表达式的参数。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
6、获取表达式的自变量参数的值 para(n,m)
int(n)指出该表达式的序号,int(m)指出自变量参数的序号。
若fcerr=-1:未对可接受表达式的二级函数进行设置,fcerr=1:指定的表达式不存在,fcerr=2:表达式未进行编译,fcerr=3:指定的自变量参数不存在。
7、计算指定序号的实数表达式的值 calrfor(n,x1,x2,... ...)
int(n)指出该表达式的序号,x1,x2,... ...为该表达式的参数,所有参数均取复数的实部。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
8、计算指定序号的整数表达式的值 califor(n,x1,x2,... ...)
int(n)指出该表达式的序号,x1,x2,... ...为该表达式的参数,所有参数均取复数的实部的整数值。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
9、合并表达式函数one(x1,x2,... ...,xn)
该函数可将多个无参表达式合并为一个表达式,以减少表达式个数,节约内存,并可提高执行速度。
该函数总是返回0值。
10、return返回函数 return(x)
结束计算并返回表达式的值为x。
2.2.5 其他常用函数
[返回页首] [返回目录]
1、设定函数递归调用的最大次数 setstackmax(n):
int(n)是1到32766之间的一个整数,函数递归调用最大次数的缺省值为16,该函数返回0。
若fcerr=1:设置错误,int(n)为非法数据。
2、设定某些函数内循环的最大次数 setcyclemax(n):
int(n)是2到2147483647之间的一个整数,函数内循环的最大次数的缺省值为1000000,该函数返回0,for、dowhile和simpintegrate函数将受到该参数的影响。
若fcerr=1:设置错误,int(n)为非法数据;fcerr=2:内存分配错误。
说明:
在以下说明中,fcerr为动态库函数运行错误代码。
FORCAL可设置同时使用多个表达式,假如设置了n个表达式,则表达式的序号分别为0、1、2、...、 i、 ...、n-1,第i个表达式简称为表达式i。
2.3.1 一个特殊的一级函数 mov(x)
[返回页首] [返回目录]
mov(x)函数将x值传送至最近使用的一个变量,因此对该变量进行了重新赋值。注意该函数实际上有两个参数,源参数为x,但目的参数即“最近使用的一个变量”却是隐含的。“最近使用的一个变量”即按照表达式的计算顺序,在mov函数执行之前最后使用的变量。详见下面的例子:
例1:(x)=x+mov[5]+x 当x为2时表达式的值为12而不是9。
例2:(x)=x+mov[x+5]+x 当x为2时表达式的值为16。
例3:(a,b,c)=one(a,mov[5],b,mov[8],mov[a+b+(c-c)],mov[a+b]) 不论计算开始时a,b,c为何值,计算结束时a为5,b为13,c为13,可以用para(n,m)函数(详见para的介绍)获取这些自变量参数。
2.3.2 全局变量及数组函数
[返回页首] [返回目录]
2.3.2.1 设置多个整数变量 newlongs(m)
该函数设置m个整数,若m<1,则删除这些整数,该函数总是返回0。
这些整数从0开始编号,即:0,1,2,3,... ...,m-1。
若fcerr=1,设置失败。
以下这些函数可以对这些整数进行各种运算操作。
1、对一个整数进行赋值 seti(n,x):
将第n个整数的值设为x,该函数返回x的值。
若fcerr=1,表示不存在第n个整数。
2、获得一个整数的值 geti(n):
获得第n个整数的值。
若fcerr=1,表示不存在第n个整数。
3、将一个数加到一个整数上并返回相加后的值 addgeti(n,x):
先将x加到第n个整数上,然后返回相加后的值。
若fcerr=1,表示不存在第n个整数。
4、获得一个整数的值后再将另一个数加到该整数上 getiadd(n,x):
该函数先返回第n个整数的值,然后将x加到第n个整数上。
若fcerr=1,表示不存在第n个整数。
2.3.2.2 设置多个一维整数数组 newlongarrays(m)
该函数设置m个一维整数数组,若m<1,则删除这些整数数组,该函数总是返回0。
这些整数数组从0开始编号,即:0,1,2,3,... ...,m-1。
若fcerr=1,设置失败。
以下这些函数可以对这些整数数组或数组元素进行各种运算操作。
1、设置一维整数数组的长度 newlongarray(n,m,x1,x2,... ...):
将第n个数组长度设为m,可以存储m个数组元素,若m<1,则删除该数组,该函数总是返回0。
这些数组的元素从0开始编号,即:0,1,2,3,... ...,m-1。
设置成功将x1,x2,... ...存储到该数组。
若fcerr=1:参数个数不能少于两个;fcerr=2:未设置多个一维整数数组;fcerr=3:不存在第n个数组;fcerr=4:数组设置失败;fcerr=5:x1,x2,... ...的个数大于m。
2、对一个数组元素进行赋值 setia(n,m,x):
该函数将x值存储到第n个数组的第m个元素位置并返回x的值。
若fcerr=1:未设置多个一维整数数组;fcerr=2:不存在第n个数组;fcerr=3:未对该数组进行设置或不存在第m个数组元素。
3、获得一个数组元素的值 getia(n,m):
该函数获得第n个数组的第m个数组元素的值。
若fcerr=1:未设置多个一维整数数组;fcerr=2:不存在第n个数组;fcerr=3:未对该数组进行设置或不存在第m个数组元素。
4、将一个数加到一个数组元素上并返回相加后的值 addgetia(n,m,x):
先将x加到第n个数组的第m个数组元素上,然后返回相加后的值。
若fcerr=1:未设置多个一维整数数组;fcerr=2:不存在第n个数组;fcerr=3:未对该数组进行设置或不存在第m个数组元素。
2.3.3 逻辑函数
[返回页首] [返回目录]
FORCAL用大于0的数表示逻辑真,小于等于0的数表示逻辑假。
1、gt(x,y):如果x>y返回1,否则返回-1。
2、ge(x,y):如果x>=y返回1,否则返回-1。
3、lt(x,y):如果x<y返回1,否则返回-1。
4、le(x,y):如果x<=y返回1,否则返回-1。
5、eq(x,y):如果x==y返回1,否则返回-1。
6、ne(x,y):如果x!=y返回1,否则返回-1。
7、and(x,y):如果x>0同时y>0返回1,否则返回-1。
8、or(x,y):如果x<0同时y<0返回-1,否则返回1。
9、not(x):如果x>0返回-1,否则返回1。
10、xor(x,y):如果x和y符号相同返回-1,否则返回1。
2.3.4 表达式相互调用及流程控制函数
[返回页首] [返回目录]
1、for循环函数 for(x,y1,y2,...,break(),...,continue(), ...,z)
自变量x为逻辑表达式,y1,y2,...,break(),...,continue(), ...为执行语句,z为增量语句。当x的值为真时,依次执行这些表达式,直到x的值为假时退出循环。当执行到break()函数时,跳出for循环,执行for循环后面的函数;当执行到continue()函数时,返回到for循环的开始语句x处继续执行。
for(x,y1,y2,...,break(),...,continue(), ...,z)即for(判断语句x,多个执行语句y1,y2,...,break(),...,continue(), ...,增量语句z)。
该函数至少要有2个自变量参数,其中第一个参数为逻辑表达式。
该函数总是返回0值。
若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。
该函数中continue()的使用会导致fcerr=1:循环次数超出限制。
2、dowhile循环函数 dowhile(x1,x2,...,break(),...,continue(),...,y)
dowhile为先执行后判断的循环函数。即先执行多个表达式x1,x2,...,break(),...,continue(),...,然后计算逻辑表达式y的值,直到y的值为假时退出循环。当执行到break()函数时,跳出dowhile循环,执行dowhile循环后面的函数;当执行到continue()函数时,返回到dowhile循环的开始语句x1处继续执行。
dowhile(x1,x2,...,break(),...,continue(),...,y)即dowhile(多个执行语句x1,x2,...,break(),...,continue(),...,判断语句y)。
该函数至少要有2个自变量参数,其中最后一个参数为逻辑表达式。
该函数总是返回0值。
若fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用,或者嵌套太深;fcerr=1:循环次数超出限制。
该函数中continue()的使用会导致fcerr=1:循环次数超出限制。
3、判断函数 if(x,y1,y2,... ...,yn)
当逻辑值x为真时,依次执行表达式y1,y2,... ...,yn,否则,不执行表达式y1,y2,... ...,yn。
该函数至少要有2个自变量参数,其中第一个参数为逻辑表达式。
该函数总是返回0值。
4、自定义分段函数 which(逻辑值1,表达式1,逻辑值2,表达式2,... ...,逻辑值n,表达式n,缺省表达式)
FORCAL从前往后检测逻辑值,当检测到逻辑真时,计算与此逻辑真对应的表达式并返回该表达式的值,如果没有检测到逻辑真,则计算缺省表达式的值作为返回值,若此时没有缺省表达式,则产生一个运行错误。
例如下式定义了一个分段函数:(x)=which[gt(x,0),2*x-1,x*x-1]。
若fcerr=1:没有参数或找不到返回值。
如果舍弃该函数的返回值,则该函数可以作为一个选择计算函数使用。
5、计算指定序号的表达式的值 calfor(n,x1,x2,... ...)
n指出该表达式的序号,x1,x2,... ...为该表达式的参数。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
6、获取表达式的自变量参数的值 para(n,m)
int(n)指出该表达式的序号,int(m)指出自变量参数的序号。
若fcerr=-1:未对可接受表达式的二级函数进行设置,fcerr=1:指定的表达式不存在,fcerr=2:表达式未进行编译,fcerr=3:指定的自变量参数不存在。
7、计算指定序号的复数表达式的值 calcfor(n,x1,y1,x2,y2,... ...)
n指出该表达式的序号,x1,y1,x2,y2,... ...为该表达式的参数,其中xi为复数的实部,yi为复数的虚部。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
8、计算指定序号的实数表达式的值 calrfor(n,x1,x2,... ...)
n指出该表达式的序号,x1,x2,... ...为该表达式的参数。
若fcerr=-1:未对可接受表达式的二级函数进行设置;fcerr=-2:直接或间接递归调用次数超出限制,可能是无穷递归调用;fcerr=1:指定的表达式不存在;fcerr=2:表达式未进行编译;fcerr=3:参数个数不匹配。
9、合并表达式函数one(x1,x2,... ...,xn)
该函数可将多个无参表达式合并为一个表达式,以减少表达式个数,节约内存,并可提高执行速度。
该函数总是返回0值。
10、return返回函数 return(x)
结束计算并返回表达式的值为x。
2.3.5 其他常用函数
[返回页首] [返回目录]
1、最大值函数 max(x1,x2,x3,... ...):
若fcerr=1:没有参数。
2、最小值函数min(x1,x2,x3,... ...):
若fcerr=1:没有参数。
3、余数函数 mod(x,y):
求x/y的余数。
4、符号传送函数 sign(x,y):
该函数的符号取y的符号,数值取x的绝对值,若y=0无符号传送,返回x值。
5、正差函数 dim(x,y):
当x>y时得x-y,否则返回0。
6、设定函数递归调用的最大次数 setstackmax(n):
n是1到32766之间的一个整数,函数递归调用最大次数的缺省值为16,该函数返回0。
若fcerr=1:设置错误,n为非法数据。
7、设定某些函数内循环的最大次数 setcyclemax(n):
n是2到2147483647之间的一个整数,函数内循环的最大次数的缺省值为1000000,该函数返回0,for、dowhile和simpintegrate函数将受到该参数的影响。
若fcerr=1:设置错误,n为非法数据;fcerr=2:内存分配错误。
3 FORCAL中的字符数据处理 [返回页首] [返回目录]
FORCAL在编译表达式时,将表达式中的字符串用一个整数代替,这个整数即该字符串的地址,使用字符串的二级函数可以根据这个地址存取这些字符串。用法请参考forcaltest.cpp中的printstr( )函数。
在编译时,对于以下几种字符串形式,FORCAL将作如下处理:
"...":为该字符串开辟存储空间,并在表达式中用一个整数即该空间的地址代替该字符串;
若一个表达式中的首字符串为"char",则表明该表达式中的字符串为公用字符串,公用字符串可被@"..."描述符访问到;
&"...":不为该字符串开辟存储空间,仅仅取同一个表达式中相同字符串的地址,如果在同一个表达式中没有相同的字符串,则返回一个出错信息,出错码为24;
@"...":不为该字符串开辟存储空间,仅仅取公用区字符串(表达式中的首字符串为"char")中相同字符串的地址,如果公用区字符串中没有相同的字符串,则返回一个出错信息,出错码为24;
$"...":不为该字符串开辟存储空间,该字符串应为一个已经编译过的表达式中的第一个字符串,如果找到这个表达式,则取该表达式的类型(1为整型、2为实型、3为复型),否则返回一个出错信息,出错码为22。
#"...":不为该字符串开辟存储空间,该字符串应为一个已经编译过的相同类型的表达式中的第一个字符串“...”,如果找到这个表达式,则取该表达式的序号,否则返回一个出错信息,出错码为23。
#"#...":不为该字符串开辟存储空间,该字符串应为一个已经编译过的表达式(可为任何类型)中的第一个字符串“...”,如果找到这个表达式,则取该表达式的序号,否则返回一个出错信息,出错码为23。
#"i#...":不为该字符串开辟存储空间,该字符串应为一个已经编译过的整数表达式中的第一个字符串“...”,如果找到这个表达式,则取该表达式的序号,否则返回一个出错信息,出错码为23。
#"r#...":不为该字符串开辟存储空间,该字符串应为一个已经编译过的实数表达式中的第一个字符串“...”,如果找到这个表达式,则取该表达式的序号,否则返回一个出错信息,出错码为23。
#"c#...":不为该字符串开辟存储空间,该字符串应为一个已经编译过的复数表达式中的第一个字符串“...”,如果找到这个表达式,则取该表达式的序号,否则返回一个出错信息,出错码为23。
在Forcal字符串中,用转义字符输入“\”和“"”:“\\”转义为字符“\”,“\"”转义为字符“"”,除此之外,没有定义其它的转义字符(“\”和其他字符的组合都是非法的)。但您可以根据需要定义自己的转义字符,可以编写一个字符串处理函数来完成这件事。通常,转义字符的处理可在编译表达式之前或之后进行,具体的做法很简单:扫描所有的Forcal字符串,处理所有的转义字符。
具体使用请参考以下例子。
4.1 使用说明
[返回页首] [返回目录]
1、该程序使用简单,请参考程序运行时的说明。
2、建议先在文本编辑器例如记事本中输入数学表达式,然后将表达式文件复制粘贴到forcaltest.exe中,这样改写表达式较为方便。
4.2 计算实例
[返回页首] [返回目录]
1、FORCAL与VC的速度比较:使用自定义外部函数speed[]即可进行比较。
2、简单的数值计算:
2+sin[2+3*sqrt(3)]*exp[5]; //实数表达式;
c:sin[2+3i]-ln[i]; //复数表达式;
3、三角形面积公式:
"area"(a,b,c)=sqrt[s*(s-a)*(s-b)*(s-c)],s=(a+b+c)/2; //定义三角形面积公式;
calfor[#"area",3,4,5];
3、变步长辛卜生一元积分:
"f"(x)=sin[x]+0.8; //定义一元函数;
SimpIntegrate(1,2,0.0001,#"f");
4、求和函数sum的用法:
"F3"(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)]}}};
sum[#"F3",0,0,1,0.011,1,2,0.11]; ?
5、有一组测定数据:0.105、0.115、0.115、0.116、0.116、0.128,求其平均值和标准偏差:
NewDoubleArrayS[1]; //申请一个数组;
NewDoubleArray[0,6,0.105,0.115,0.115,0.116,0.116,0.128]; //给数组赋初值;
"f"(x)=x; //定义计算平均值用到的函数;
DataArraySum(#"f",0,6,0)/6; //计算平均值;
"g"(x)=[x-DataArraySum(#"f",0,6,0)/6]^2; //定义计算标准偏差用到的函数;
sqrt{DataArraySum(#"g",0,6,0)/5}; //计算标准偏差;
6、一个字符串函数的例子:
"aa ""*"" bb"(:i,j)=one
{i=20,
for{i,
printstr[&"aa "],
j=0,
for{i-j,
printstr[&"*"],
j=j+1
},
printstr[&" bb"],
end[],
i=i-1
}
} ?
7、mov函数用法及速度:
"ff"(z:x,y)=-clock()+one(x,mov[0],z,mov[0])+
for{le[x,1000], // 外for循环的逻辑表达式;
y,mov[0],
for{le[y,1000], // 内for循环的逻辑表达式;
mov[sin(x)+cos(x-y)+z], // 内for循环的执行语句;
mov[y+1] // 内for循环的增量语句;
},
mov[x+1] // 外for循环的增量语句;
}
+clock() ;
calfor[#"ff",0]; // 计算结果为运行时间[毫秒];
para[#"ff",0] ? //获得以上表达式中的z值;
比较:
"ff"(z:x,y)=-clock()+one(x=0,z=0)+
for{le[x,1000], // 外for循环的逻辑表达式;
y=0,
for{le[y,1000], // 内for循环的逻辑表达式;
z=z+sin(x)+cos(x-y), // 内for循环的执行语句;
y=y+1 // 内for循环的增量语句;
},
x=x+1 // 外for循环的增量语句;
}
+clock() ;
calfor[#"ff",0]; // 计算结果为运行时间[毫秒];
para[#"ff",0] ? //获得以上表达式中的z值;
8、数据求和函数datasum的用法:
"F4"(x,y)=x*y ;// 求和公式;
DataSum[#"F4",0,1,2,3,4,5,6,7,8,9,10] ?
说明:对于式子F(x,y)=x*y,求x,y分别取1,2、3,4、5,6、7,8、9,10时的值的和。即求F[1,2]+F[3,4]+F[5,6]+F[7,8]+F[9,10]的值。
9、break()和continue()函数的用法:
NewDoubleS(10);//用NewDoubleS申请10个双精度数;
SetD[0,0]+SetD[1,0]+SetD[2,999];
dowhile{if [ge[getd(0),100], break()],
dowhile{AddGetD[1,1],
which {le[GetD(1),200], continue(), break()},
SetD[2,888]
},
AddGetD[0,1]
};
GetD[0] ; //获得双精度数0终值:100;
GetD[1] ; //获得双精度数1终值:300;
GetD[2] ; //获得双精度数2终值:999。
10、使用常量:
pi; pi[]-pi; ee; _999_;
11、公用字符串示例:
"char" "aaaaa" "bbbbb" "ccccc"; //公用字符串;
"char" "11111" "22222" "33333"; //公用字符串;
//printstr[&"bbbbb"]; //不能用&取公用字符串的地址;
printstr[@"bbbbb"]; //用@取公用字符串的地址;
printstr[@"11111"];
12、试试这个函数,该函数将给出所有目前正在使用的字符串:fcstr[]。
4.3 源代码
[返回页首] [返回目录]
//可以用VC++6.0编译运行这个程序,请使用Build->Set Active Configuration->Win32 Release选项。
#include <windows.h>
#include <time.h>
#include "math.h"
#include <iomanip.h>
#define FC_INT_MAX 32766 //整数最大值;
#define CH_FILE_MAX 1001 //CH_FILE_MAX设置表达式文件的最大长度;
#define CH_LINE_MAX 102 //CH_LINE_MAX设置每行最多容纳的字符数;
#define FCSTR_MAX 100 //FCSTR_MAX设置forcal可用的字符串数组大小;
#define FOR_MAX 50 //整数、实数、复数表达式的最大个数都设置为FOR_MAX个;
HINSTANCE handlerdll=NULL;
typedef const char * (* pVER) (void);
typedef bool (* pSETFORNUM) (int);
typedef void (* pDELETEDLL) (void);
typedef int (* pRCOM) (int ,char [],int &);
typedef int (* pFCERR) (char *&);
typedef int (* pFCERRNUM) (void);
typedef double *(* pGETIN) (int );
typedef double (* pRCALS) (int );
typedef bool (*pSETFCFUN) (char **,int *,double (**)(int ,double *)); //设置外部函数;
typedef void (*pSETFCERR) (int ,char *); //设置外部函数运行错误,字符串指针指出出错函数名;
typedef double **(* pGETALLIN) (void);
typedef bool *(* pGETFORTRUE) (void);
typedef int *(* pGETVARNUM) (void);
typedef void (* pUSERCI) (void);
typedef bool (* pSETFCSTRMAX) (long);
typedef char **(* pGETFCSTR) (long *&);
typedef void (* pINITFCSTR) (void);
typedef void (* pSETDOUBLECONST) (char **,double *);
//复数
typedef bool (* pCSETFORNUM) (int);
typedef int (* pCCOM) (int ,char [],int &);
typedef int (* pCFCERR) (char *&);
typedef _complex (* pCCALS) (int );
typedef _complex **(* pCGETALLIN) (void);
//整数
typedef bool (* pISETFORNUM) (int);
typedef int (* pICOM) (int ,char [],int &);
typedef int (* pIFCERR) (char *&);
typedef long (* pICALS) (int );
typedef long **(* pIGETALLIN) (void);
pVER pver;
pSETFORNUM psetfornum;
pDELETEDLL pdeletedll;
pFCERRNUM pfcerrnum;
pRCOM prcom;
pFCERR pfcerr;
pGETIN pgetin;
pRCALS prcals;
pSETFCFUN psetfcfun;
pSETFCERR psetfcerr;
pGETALLIN pgetallin;
pGETFORTRUE pgetfortrue;
pGETVARNUM pgetvarnum;
pUSERCI puserci;
pSETFCSTRMAX psetfcstrmax;
pGETFCSTR pgetfcstr;
pINITFCSTR pinitfcstr;
pSETDOUBLECONST psetdoubleconst;
//复数
pCSETFORNUM pcsetfornum;
pCCOM pccom;
pCFCERR pcfcerr;
pCCALS pccals;
pCGETALLIN pcgetallin;
//整数
pISETFORNUM pisetfornum;
pICOM picom;
pIFCERR pifcerr;
pICALS picals;
pIGETALLIN pigetallin;
//定义几个可由FORCAL调用的实数外部函数;
//复数和整数外部函数的定义方法与实数外部函数的定义方法类似。
double add(int ,double *);
double pi(int ,double *);
double sintegrate(int ,double *);
double average(int ,double *);
double speed(int ,double *);
double print(int ,double *);
double printstr(int ,double *);
double end(int ,double *);
double fcstr(int ,double *);
double fc_clock(int ,double *);
char *funname[]={"add","pi","sintegrate","average","speed","print","printstr","end","fcstr","clock",""}; //外部函数名;
int funzbl[]={1,-1,-2,-2,-1,0,0,-2,-2,-1}; //-2表示有不确定的多个自变量,-1表示有0个自变量,0表示有1个自变量,1表示有2个自变量;
double (*funcal[])(int ,double *)={add,pi,sintegrate,average,speed,print,printstr,end,fcstr,fc_clock}; //外部函数指针数组;
//定义常量;
char *double_str_const[]={"pi","ee","_999_",""};
double double_const[]={3.14,2.718,999.0};
int *forzbl; //存放各个表达式的自变量个数;
bool *fortrue; //存放各个表达式的编译状态,表达式编译通过时设为true;
int fc_fornum=FOR_MAX; //存放设定的同时可用的表达式的个数;
char **fc_str; //存放forcal所用的字符串数组指针;
long *fc_strmax; //存放字符子串长度;
char for_flag[3*FOR_MAX+1]; //存放表达式标记,大小为整数、实数、复数表达式的最大个数之和+1;
int for_number[3*FOR_MAX]; //存放表达式序号,大小为整数、实数、复数表达式的最大个数之和;
bool comfor(char *chFile); //编译表达式;
void exefor(void); //执行表达式;
void main(void)
{char ch,chLine[CH_LINE_MAX],chFile[CH_FILE_MAX]; //chFile存放表达式文件;
int m,n;
handlerdll=LoadLibrary("forcal.dll"); //加载动态库forcal.dll;
if(!handlerdll) {cout<<"找不到forcal.dll!请将该库放到WINDOWS的搜索路径内!\n\n请输入任意字符后按回车键Enter退
出!"<<endl; cin>>chLine; return;}
//以下几个语句获取forcal.dll中所调用函数的地址;
pver=(pVER) GetProcAddress(handlerdll,"ver");
psetfornum=(pSETFORNUM) GetProcAddress(handlerdll,"setfornum");
pdeletedll=(pDELETEDLL) GetProcAddress(handlerdll,"deletedll");
prcom=(pRCOM) GetProcAddress(handlerdll,"rcom");
pfcerr=(pFCERR) GetProcAddress(handlerdll,"fcerr");
pgetin=(pGETIN) GetProcAddress(handlerdll,"getin");
prcals=(pRCALS) GetProcAddress(handlerdll,"rcals");
psetfcfun=(pSETFCFUN) GetProcAddress(handlerdll,"setfcfun");
psetfcerr=(pSETFCERR) GetProcAddress(handlerdll,"setfcerr");
pgetallin=(pGETALLIN) GetProcAddress(handlerdll,"getallin");
pgetfortrue=(pGETFORTRUE) GetProcAddress(handlerdll,"getfortrue");
pfcerrnum=(pFCERRNUM) GetProcAddress(handlerdll,"fcerrnum");
pgetvarnum=(pGETVARNUM) GetProcAddress(handlerdll,"getvarnum");
puserci=(pUSERCI) GetProcAddress(handlerdll,"userci");
psetfcstrmax=(pSETFCSTRMAX) GetProcAddress(handlerdll,"setfcstrmax");
pgetfcstr=(pGETFCSTR) GetProcAddress(handlerdll,"getfcstr");
pinitfcstr=(pINITFCSTR) GetProcAddress(handlerdll,"initfcstr");
psetdoubleconst=(pSETDOUBLECONST) GetProcAddress(handlerdll,"setdoubleconst");
//复数
pcsetfornum=(pCSETFORNUM) GetProcAddress(handlerdll,"Csetfornum");
pccom=(pCCOM) GetProcAddress(handlerdll,"Ccom");
pcfcerr=(pCFCERR) GetProcAddress(handlerdll,"Cfcerr");
pccals=(pCCALS) GetProcAddress(handlerdll,"Ccals");
pcgetallin=(pCGETALLIN) GetProcAddress(handlerdll,"Cgetallin");
//整数
pisetfornum=(pISETFORNUM) GetProcAddress(handlerdll,"Isetfornum");
picom=(pICOM) GetProcAddress(handlerdll,"Icom");
pifcerr=(pIFCERR) GetProcAddress(handlerdll,"Ifcerr");
picals=(pICALS) GetProcAddress(handlerdll,"Icals");
pigetallin=(pIGETALLIN) GetProcAddress(handlerdll,"Igetallin");
psetdoubleconst(double_str_const,double_const); //设置常量;
psetfcfun(funname,funzbl,funcal); //设置外部函数;
psetfcstrmax(FCSTR_MAX); //设置forcal可用的字符串数组大小;
fc_str=pgetfcstr(fc_strmax); //获得forcal所用的字符串数组指针和存放字符子串长度的数组指针;
if(!psetfornum(fc_fornum+1)) goto end; //设置fc_fornum+1个实数表达式;
if(!pcsetfornum(fc_fornum)) goto end; //设置fc_fornum个复数表达式;
if(!pisetfornum(fc_fornum)) goto end; //设置fc_fornum个整数表达式;
puserci(); //使实数、复数和整数表达式可以相互调用;
fortrue=pgetfortrue(); //获得指向存放各表达式编译状态的数组的指针,这个参数在设计外部函数时要用到;
forzbl=pgetvarnum(); //获得指向存放各个表达式的自变量个数的数组的指针,这个参数在设计外部函数时要用到;
cout<<pver()<<endl<<endl; //获取版本信息;
cout<<"FORCAL演示程序:编译计算多个表达式的值"<<endl<<endl<<setprecision(20);
cout<<"注意1:各个表达式之间用分号‘;’分隔;"<<endl;
cout<<"注意2:以字母c:开头的表达式为复数表达式,以字母i:开头的表达式为整数表达式;"<<endl;
cout<<"注意3:对于有参数的表达式,只编译,不计算;"<<endl;
cout<<"注意4:最多可用的整数、实数、复数表达式的个数均为"<<FOR_MAX<<"个;"<<endl;
cout<<"注意5:表达式中最多可用"<<FCSTR_MAX<<"个字符串;"<<endl;
cout<<"注意6:表达式文件最多接收"<<CH_FILE_MAX-1<<"个字符,每行最多接收"<<CH_LINE_MAX-2<<"个字符;"<<endl;
cout<<"注意7:在每行中两个‘//’后的字符将被忽略,问号字符‘?’表示该文件的结束。"<<endl<<endl;
ch=' ';
//循环计算部分;
while(ch!='y'&&ch!='Y')
{cout<<"请输入表达式文件:"<<endl<<endl;
n=0;
while(1)
{cin.getline(chLine,CH_LINE_MAX-2,'\n'); //输入字符串表达式;
for(m=0;chLine[m];m++)
{if(chLine[m]=='/'&&chLine[m+1]=='/'||chLine[m]=='?'||n==CH_FILE_MAX-1) break;
if(chLine[m]!=' '&&chLine[m]!='\t') chFile[n++]=chLine[m];
}
if(chLine[m]=='?'||n==CH_FILE_MAX-1) {chFile[n]='\0'; break;} //遇到字符?或字符数组满时,表达式输入结束。
}
pinitfcstr(); //初始化字符串空间;
if(comfor(chFile)) //编译计算;
{cout<<endl<<"计算结果:"<<endl<<endl;
exefor();
}
cout<<endl<<"是否退出?(Yes/No):";
cin>>ch;
cout<<endl;
}
end:
pdeletedll(); //释放动态库申请的空间;
FreeLibrary(handlerdll); //释放动态库;
}
bool comfor(char *chFile) //编译表达式;
{int ii,rr,cc,n,nn;
long nch,i,j,kkk;
nch=(int)strlen(chFile);
if(!nch) return false;
j=-1; ii=-1; rr=-1; cc=-1; kkk=-1;
do{i=j+1;
if(chFile[i]==';') {j++; continue;}
if(chFile[i]=='\0') break;
for(j=i;chFile[j];j++) {if(chFile[j]==';') break;}
chFile[j]='\0'; kkk++;
if(j-i>FC_INT_MAX-5) {cout<<"\r\n编译错误:表达式太长。\r\n"; return false;}
if(chFile[i]=='i'&&chFile[i+1]==':')
{ii++;
if(ii==fc_fornum) {cout<<"\r\n整数表达式太多!\r\n"; return false;}
n=i+2;
n=picom(ii,&chFile[n],nn);
if(n) //编译错误;
{cout<<"\r\n整数表达式:"<<&chFile[i]<<endl<<"编译错误代码:"<<n<<endl;
return false;
}
else
{if(nn==-1) for_number[kkk]=ii;
else for_number[kkk]=-1;
for_flag[kkk]=1;
}
}
else if(chFile[i]=='c'&&chFile[i+1]==':')
{cc++;
if(cc==fc_fornum) {cout<<"\r\n复数表达式太多!\r\n"; return false;}
n=i+2;
n=pccom(cc,&chFile[n],nn);
if(n) //编译错误;
{cout<<"\r\n复数表达式:"<<&chFile[i]<<endl<<"编译错误代码:"<<n<<endl;
return false;
}
else
{if(nn==-1) for_number[kkk]=cc;
else for_number[kkk]=-1;
for_flag[kkk]=3;
}
}
else
{rr++;
if(rr==fc_fornum) {cout<<"\r\n实数表达式太多!\r\n"; return false;}
n=i;
n=prcom(rr,&chFile[n],nn);
if(n) //编译错误;
{cout<<"\r\n实数表达式:"<<&chFile[i]<<endl<<"编译错误代码:"<<n<<endl;
return false;
}
else
{if(nn==-1) for_number[kkk]=rr;
else for_number[kkk]=-1;
for_flag[kkk]=2;
}
}
}while(j!=nch);
for_flag[++kkk]=0;
return true;
}
void exefor(void) //执行表达式;
{int i;
char *perr; //perr指向出现FORCAL运行错误时的出错函数名;
_complex cc;
i=0;
while(for_flag[i])
{if(for_number[i]>=0)
{if(for_flag[i]==1)
{cout<<"i:"<<picals(for_number[i])<<endl;}
else if(for_flag[i]==2)
{cout<<prcals(for_number[i])<<endl;}
else
{cc=pccals(for_number[i]);
cout<<"c:"<<cc.x;
if(cc.y>=0.0) cout<<"+";
cout<<cc.y<<"i"<<endl;
}
}
i++;
}
//检查FORCAL运行错误;
i=pifcerr(perr);
if(i!=0) cout<<"\r\nFORCAL运行错误,整数表达式,函数名: "<<perr<<" 错误代码:"<<i<<endl;
i=pfcerr(perr);
if(i!=0) cout<<"\r\nFORCAL运行错误,实数表达式,函数名: "<<perr<<" 错误代码:"<<i<<endl;
i=pcfcerr(perr);
if(i!=0) cout<<"\r\nFORCAL运行错误,复数表达式,函数名: "<<perr<<" 错误代码:"<<i<<endl;
}
int matherr(struct _exception *err) //标准数学错误检测;
{cout<<endl<<"标准数学错误! 出错函数名:"<<err->name<<endl<<endl;
return 0;
}
//向FORCAL注册的几个基本函数[外部函数];
double add(int m,double *x) //计算两个数的和;
{return x[0]+x[1];
}
double pi(int m,double *x) //pi常量函数;
{return 3.14159265358979;
}
double sintegrate(int m,double *xx) //一元积分函数;
{double a,b,eps,*pzbl; //a为积分下限,b为积分上限,eps为积分精度要求,pzbl为指向表达式自变量数组的指针;
int n,k,nfor; //nfor指出对第nfor个表达式进行积分;
double h,t1,t2,s1,s2,ep,p,x;
static int sintegratenum=0,sintegratemax=10; //sintegratemax为递归调用的最大次数,sintegratenum记录递归调用的实际次数;
if(pfcerrnum()!=0) goto end; //pfcerrnum()函数获取Forcal的运行错误,若出现过任何运行错误,不再进行计算;
if(++sintegratenum>sintegratemax) {if(pfcerrnum()==0) psetfcerr(-2,funname[2]); goto end;} //递归次数超出限制,用psetfcerr()函数设定运行错误;
if(fc_fornum<1) {if(pfcerrnum()==0) psetfcerr(-1,funname[2]); goto end;} //未设置可接受外部函数功能;
if(m<3) {if(pfcerrnum()==0) psetfcerr(3,funname[2]); goto end;} //函数的参数个数不匹配;
nfor=(int)xx[3]; //nfor指出对第nfor个表达式进行积分;
if(nfor<0||nfor>=fc_fornum) {if(pfcerrnum()==0) psetfcerr(1,funname[2]); goto end;} //指定的表达式不存在;
if(!fortrue[nfor]) {if(pfcerrnum()==0) psetfcerr(2,funname[2]); goto end;} //指定的表达式编译未通过,fortrue数组存放表达式的编译状态;
n=forzbl[nfor]; //获取该表达式的自变量个数;
if(m!=3+n) {if(pfcerrnum()==0) psetfcerr(3,funname[2]); goto end;} //函数的参数个数不匹配;
pzbl=pgetin(nfor); //pgetin(nfor)获取第nfor个表达式的自变量指针;
for(k=1;k<=n;k++) pzbl[k]=xx[3+k]; //当n>0时,进行两个表达式之间的参数传递;
a=xx[0]; b=xx[1]; eps=xx[2];
////////////////////////////////////以下进行积分!
n=1; h=b-a;
pzbl[0]=a; x=prcals(nfor); //prcals(nfor)计算第nfor个表达式的值;
pzbl[0]=b;
t1=h*(x+prcals(nfor))/2.0;
s1=t1;
ep=eps+1.0;
while (ep>=eps)
{ p=0.0;
for (k=0;k<=n-1;k++)
{ pzbl[0]=a+(k+0.5)*h;
p=p+prcals(nfor);
}
t2=(t1+h*p)/2.0;
s2=(4.0*t2-t1)/3.0;
ep=fabs(s2-s1);
t1=t2; s1=s2; n=n+n; h=h/2.0;
}
////////////////////////////////以上进行积分!
if(pfcerrnum()==0) {sintegratenum--; return(s2);} //未发生任何错误退出时,递归次数减1;
end: //出错时,递归次数设为0;
sintegratenum=0; return 0.0;
}
double average(int m,double *x) //计算平均值函数;
{int i;
double ave;
if(m==-1) {if(pfcerrnum()==0) psetfcerr(-1,funname[3]); return 0.0;} //如果average()没有参数,返回一个FORCAL运行错误;
ave=0.0;
for(i=0;i<=m;i++) ave=ave+x[i];
return ave/(m+1);
}
double speed(int m,double *xx) //FORCAL与VC的速度比较;
{char aa[]="(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)]}}}"; //数学表达式;
int n;
double z,*dd,x,y;
clock_t old,now;
prcom(fc_fornum,aa,n);
cout<<endl<<"FORCAL与VC的速度比较:"<<endl;
cout<<endl<<"表达式:"<<aa<<endl;
cout<<endl<<"FORCALDLL正对表达式进行循环求和计算,请等待... ..."<<endl;
z=0.0; old=clock();
dd=pgetin(fc_fornum);
for(dd[0]=0.0;dd[0]<=1.0;dd[0]=dd[0]+0.0011)
for(dd[1]=1.0;dd[1]<=2.0;dd[1]=dd[1]+0.0011)
z=z+prcals(fc_fornum);
now=clock();
cout<<"forcal计算结果:"<<setprecision(20)<<z;
cout<<" 运行时间:"<<now-old<<" 即: "<<(double)(now-old)/CLOCKS_PER_SEC<<"秒"<<endl<<endl;
cout<<"VC++ 正对表达式进行循环求和计算,请等待... ..."<<endl;
z=0.0; old=clock();
for(x=0.0;x<=1.0;x=x+0.0011)
for(y=1.0;y<=2.0;y=y+0.0011)
{z=z+cos(1.0-sin(1.2*pow(x+0.1,y/2.0-x)+cos(1.0-sin(1.2*pow(x+0.2,y/3.0-x))))-cos(1.0-sin(1.2*pow(x+0.3,y/4.0-x)))-cos(1.0-sin(1.2*pow(x+0.4,y/5.0-x)+cos(1.0-sin(1.2*pow(x+0.5,y/6.0-x))))-cos(1.0-sin(1.2*pow(x+0.6,y/7.0-x)))));
}
now=clock();
cout<<"VC++ 计算结果:"<<setprecision(20)<<z<<' ';
cout<<" 运行时间:"<<now-old<<" 即: "<<(double)(now-old)/CLOCKS_PER_SEC<<"秒"<<endl<<endl;
return 0.0;
}
double print(int m,double *x) //输出一个实数;
{cout<<setprecision(20)<<*x<<" ";
return *x;
}
double printstr(int m,double *x) //输出一个字符串;
{cout<<fc_str[(long)x[0]]; return 0.0;}
double end(int m,double *x) //输出一个换行符;
{cout<<endl; return 0.0;}
double fcstr(int m,double *x) //输出全部forcal字符串及长度;
{int i;
for(i=0;i<FCSTR_MAX;i++)
{if(fc_str[i]) cout<<i<<": "<<fc_str[i]<<" 长度:"<<fc_strmax[i]<<endl;}
return 0.0;
}
double fc_clock(int ,double *)
{return (double)clock();
}
//很多人会对最简单使用的例子感兴趣,以下就是一个使用FORCAL的最简单的例子。
//可以用VC++6.0编译运行这个程序,请使用Build->Set Active Configuration->Win32 Release选项。
#include <windows.h>
#include <iomanip.h>
HINSTANCE handlerdll=NULL;
typedef bool (* pSETFORNUM) (int);
typedef void (* pDELETEDLL) (void);
typedef int (* pRCOM) (int ,char [],int &);
typedef double (* pRCALS) (int );
pSETFORNUM psetfornum;
pDELETEDLL pdeletedll;
pRCOM prcom;
pRCALS prcals;
void main(void)
{char chLine[256]; //chLine存放表达式;
int m,n;
handlerdll=LoadLibrary("forcal.dll"); //加载动态库forcal.dll;
if(!handlerdll) {cout<<"找不到forcal.dll!请将该库放到WINDOWS的搜索路径内!\n\n请输入任意字符后按回车键Enter退出!"<<endl; cin>>chLine; return;}
//以下几个语句获取forcal.dll中所调用函数的地址;
psetfornum=(pSETFORNUM) GetProcAddress(handlerdll,"setfornum");
pdeletedll=(pDELETEDLL) GetProcAddress(handlerdll,"deletedll");
prcom=(pRCOM) GetProcAddress(handlerdll,"rcom");
prcals=(pRCALS) GetProcAddress(handlerdll,"rcals");
if(!psetfornum(1)) goto end; //设置1个实数表达式;
cout<<setprecision(20);
//循环计算部分;
while(1)
{cout<<">> 使用FORCAL的最简单的例子,请输入表达式(首字符为 q 将退出程序):"<<endl<<endl;
cin>>chLine;
if(chLine[0]=='q'||chLine[0]=='Q') break;
m=prcom(0,chLine,n); //编译表达式;
if(m)
{cout<<endl<<"编译错误代码:"<<m<<endl<<endl;}
else
{cout<<endl<<"计算结果:"<<prcals(0)<<endl<<endl;} //计算表达式;
}
end:
pdeletedll(); //释放动态库申请的空间;
FreeLibrary(handlerdll); //释放动态库;
}
请先用GetForcalID.exe获取序列号,以便将Forcal正式版安装到您的计算机上。
如果通过网路中国共享软件注册中心(www.softreg.com.cn)进行注册,可点击这里进入注册页面。
其他注册方式请访问作者网站,作者主页:http://forcal.yeah.net/或http://wangluwanglu.yeah.net/。
如有任何问题,请与作者联系。
E-mail:wanglu71641@sina.com 或
wanglu@shareware.com.cn 或 wangluwanglu@163.com
版权所有© Forcal数学软件
2002-2004,保留所有权利
E-mail: wanglu71641@sina.com
最近更新: 2004年08月10日