Forcal演示程序
用测试程序ForcalTest、ForcalDemo和MForcalDemo演示Forcal
1 使用说明
1.1 该程序使用简单,请参考程序运行时的说明。补充说明如下:
在ForcalTest或ForcalDemo中使用的#MODULE#、#END#、~、i:、r:、c:、:、!等称为编译指令,用以确定一个表达式的类型、所在模块、是否私有函数等属性。这些编译指令必须位于表达式的开头,有些指令能同时使用,有些指令不能同时使用,并且在使用时有一定的次序,按先后顺序依次为:
1)编译指令#MODULE#和#END#必须在表达式的最前面,一般单独成行。#MODULE#表示开始一个子模块的编译,#END#表示回到主模块的编译。
2)~表示该表达式是一个全局表达式,否则是私有表达式。该编译符对主模块(0#模块)中的表达式无效,主模块(0#模块)中的表达式都是私有表达式。
3)编译指令i:、r:、c:不能混合使用,只能使用其中的一个,强制指定表达式的类型。如果都没有用,表达式按实数类型进行编译。
4)编译指令:、!不能混合使用,只能使用其中的一个。“:”表示该表达式只编译,不执行;“!”表示该表达式编译后立即执行,但以后执行时不再自动执行。
如果表达式前没有使用任何一个编译指令,则按实数类型编译为私有表达式,若该表达式是无参表达式,则执行模块时将自动执行。
在MForcalDemo中支持以上语法并有所增强,参考MForcal使用说明。
1.2 在使用ForcalTest时,建议先在文本编辑器例如记事本中输入表达式,然后将表达式文件复制粘贴到forcaltest.exe中,这样改写表达式较为方便。
2 在ForcalTest中定义的二级函数
2.1 my::add(2,3):计算两个数的和。
2.2 my::pi():常量函数,圆周率pi。
2.3 my::平均值(x1,x2,x3,... ...):计算多个数的平均值。
该函数至少需要一个参数,否则返回一个FORCAL运行错误,代码为1。
2.4 SIntegrate(a,b,eps,"F"):变步长辛卜生一元积分函数。
a为积分下限,b为积分上限,eps为积分精度要求,F为被积函数。
例子:
a(x)=sin[x]+0.8;
SIntegrate(1,2,0.0001,"a");
该函数会返回FORCAL运行错误,错误代码意义: 1:应使用字符串传递表达式名称;2:指定的表达式不存在;3:指定的表达式不是一元函数。
2.5 speed():比较FORCAL和VC的计算速度。
2.6 print(2.3):输出一个实数。
2.7 PrintStr("hello !"):输出一个近程静态Forcal字符串。
PrintStr(pFor,"hello !"):输出一个远程静态Forcal字符串,其中pFor为表达式句柄,可由函数HFor("ForName",ForType)获得。
2.8 end():输出一个换行符。
2.9 CalFor("f",x1,x2,...,xn):在运行时调用实数表达式"f";x1,x2,...,xn为表达式的参数。
该函数会返回FORCAL运行错误,错误代码意义: 1:至少需要一个参数;2:参数不匹配;3:找不到表达式。
2.10 CalHFor(pFor,x1,x2,...,xn):在运行时调用实数表达式pFor;x1,x2,...,xn为表达式的参数。 其中pFor为表达式句柄,可由函数HFor("ForName",ForType)获得。
该函数会返回FORCAL运行错误,错误代码意义: 1:至少需要一个参数;2:参数不匹配;3:非法的表达式句柄。
另外,forcaltest中定义了两个常量:_e_和Pi。
3 用ForcalTest演示的 简单例子
大部分例子中使用了ForcalTest中定义的二级函数和常量,因而
这些例子只能在ForcalTest中运行。
3.1 FORCAL与VC的速度比较[只能在ForcalTest中运行]
speed(); //Forcal一级函数的速度是最快的
3.2 简单的数值计算
2+sin[2+3*sqrt(3)]*exp[5]; //实数表达式;
i:222%5+8; //整数表达式;
c:sin[2+3i]-ln[i]; //复数表达式;
3.3 三角形面积公式
F(a,b,c:s)= s=(a+b+c)/2,sqrt[s*(s-a)*(s-b)*(s-c)]; //定义三角形面积公式;
F[3,4,5];
3.4 变步长辛卜生一元积分[只能在ForcalTest中 运行]
f(x)=sin[x]+0.8; //定义一元函数;
SIntegrate(1,2,0.0001,"f");
3.5 求和函数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,1,0.011,1,2,0.11]; ?
3.6 循环的嵌套:打印字符串[只能在ForcalTest中 运行]
(:i,j)=
{
i=20,
while
{
i,
PrintStr["aa "],
j=0,
while
{
i-j,
PrintStr["*"],
j++
},
PrintStr[" bb"],
end[],
i--
}
} ?
3.7 循环的嵌套:将1~10这几个数字在屏幕上打印10遍[只能在ForcalTest中 运行]
(:i,j)=
{
i=0,
while
{
i<10, //循环判断语句;
j=1,
while
{
j<11, //循环判断语句;
print(j),
j++
},
end(),
i++
}
}
3.8 检测一个数是否为素数
Prime(n:i)=
{
i=1,
while
{
i<n/2,
if
{
!fmod(n,++i), //i先增1,然后进行模运算;
printff["\r\n{1,r}不是一个素数!",n],
return[i]
}
},
printff["\r\n{1,r}是一个素数!",n],
i
};
Prime[5]; //检测5是否是一个素数;
3.9 递归打印数据[只能在ForcalTest中 运行]
SetRealStackMax[1000];
z_a(i)=if[i<10,z_a(i+1),print(i)]; //按降序打印;
z_a[0];
a_z(i)=if[i<10,print(i),a_z(i+1)]; //按升序打印;
a_z[0];
3.10 无限循环的退出
while[1,1]; //无限循环函数,可通过另一线程“退出FORCAL!!!”;
3.11 使用常量和常量函数[只能在ForcalTest中 运行]
_e_; Pi; my::pi[];
3.12 输出远程静态Forcal字符串 :例子1[只能在ForcalTest中运行]
aa()=PrintStr(HFor("aa",2),"hello !");
3.13 输出远程静态Forcal字符串 :例子2[只能在ForcalTest中运行]
bb()="adfg";
PrintStr[HFor("bb",2),bb()];
3.14 CalFor(...)的用法:在运行时调用实数表达式[只能在ForcalTest中 运行]
aa(x)=x+8;
CalFor["aa",7];
3.15 CalHFor(...)的用法:在运行时调用实数表达式[只能在ForcalTest中 运行]
aa(x)=x+8;
CalHFor[HFor("aa",2),7];
3.16 模块及二级函数命名空间[只能在ForcalTest中 运行]
#MODULE#
printff("在子模块中使用二级函数命名空间my:\r\n");
!using("my");
add(1,2);
pi();
平均值(1,2,3,4,5);
#END#
printff("在主模块中使用二级函数命名空间my:\r\n");
!using("my");
add(2,3);
pi();
平均值(6,7,8,9,10);
4 复杂例子
4.1 八皇后问题
据测定,以下八皇后问题,Forcal的运行速度约为C++的1/10。
// 在运行不同的程序时,Forcal的速度,从接近C++到只有C++速度的几十分之一。
// Forcal的建议是:对运行时间较长的程序,如确有必要,设计成二级函数由Forcal调用,从而获得接近C++速度的性能。
// Forcal与C++是无缝链接的。故C++能实现的功能,借助二级函数,Forcal完全可以实现。
// 但没有Forcal支持的C++程序,将无法获得高效率地实时编译计算字符串表达式的功能。
// 据测定,以下八皇后问题,Forcal的运行速度约为C++的1/10。
// 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。
// 该问题是19世纪著名的数学家高斯1850年提出:在8×8格的国际象棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
// 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
// 以下算法是从网上搜来的,该算法没有最终给出排列组合,仅仅给出有多少种组合,但是算法确实十分奥妙。
//Forcal源程序
i:(::sum,upperlim)= sum=0,upperlim=1,SetIntStackMax(1000);
i:test(row, ld, rd : pos,p : sum,upperlim)=
{
which
{ row != upperlim,
{ pos = and{upperlim , not[row.or(ld).or(rd)]},
while{ pos,
p = and(pos,-pos),
pos = pos -p,
test(row+p, shl(ld+p,1), shr(rd+p,1))
}
},
sum++
}
};
i:main(:tm,n:sum,upperlim)=
{
n=15,
tm=sys::clock(),
printff("Queens:{1,i}, ",n),
upperlim=shl(upperlim,n)-1,
test(0,0,0),
printff("sum:{1,i}, {2,i}毫秒.\r\n",sum,sys::clock()-tm)
};Forcal运行结果:
Queens:15, sum:2279184, 59547毫秒.
完成相同功能的C++程序:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long sum=0,upperlim=1;
void test(long row, long ld, long rd)
{
if (row != upperlim)
{
long pos = upperlim & ~(row | ld | rd);
while (pos){
long p = pos& -pos;
pos -= p;
test(row+p, (ld+p)<<1, (rd+p)>>1);
}
}
else
sum++;
}
int main(int argc, char *argv[])
{
time_t tm;
int n=15;
if(argc!=1)n=atoi(argv[1]);
tm=time(0);
if((n<1)||(n>32))
{
printf(" heh..I can’t calculate that.\n");
exit(-1);
}
printf("%d Queens\n",n);
upperlim=(upperlim<<n)-1;
test(0,0,0);
printf("Number of solutions is %ld, %d seconds\n", sum,(int)(time(0)-tm));
}
VC运行结果:
15 Queens
Number of solutions is 2279184, 6 seconds
4.2 一段有趣的程序
在这个网页看到一篇各种语言运行速度比较的文章,摘抄如下:
— Erik Wrenholt (erik -at- timestretch.com) 2005-09-20
Language Time Relative Speed C gcc-4.0.1 0.05 seconds 1.00 x ocaml compiled 3.09.2 0.05 seconds 1.00 x SBCL 1.0.2 0.13 seconds 2.55 x Java 1.4.2 0.40 seconds 8.00 x Io 20070410 Vector 1.40 seconds 28.09 x Lua 5.1 1.50 seconds 30.00 x ocaml bytecode 3.09.2 3.76 seconds 75.15 x Python 2.5.1 9.99 seconds 199.80 x Ghostscript 8.51 11.66 seconds 233.12 x Perl 5.8.6 Optimized 12.37 seconds 247.34 x TCL 8.4 Optimized 16.00 seconds 320.00 x Perl 5.8.6 21.75 seconds 435.00 x PHP 5.1.4 23.12 seconds 462.40 x Javascript SpiderMonkey v1.6 31.06 seconds 621.27 x Ruby 1.8.4 34.31 seconds 686.18 x Emacs Lisp 47.25 seconds 945.00 x Applescript 71.75 seconds 1435.00 x Io 20070410 85.26 seconds 1705.13 x 用以上网址提供的c代码与forcal比较,c代码改写为vs 2008可接受的形式,编译运行,结果如下: #include "stdafx.h" #include <math.h> #include <time.h> #define BAILOUT 16 #define MAX_ITERATIONS 1000 int mandelbrot(double x, double y) { double cr = y - 0.5; double ci = x; double zi = 0.0; double zr = 0.0; int i = 0; while(1) { i ++; double temp = zr * zi; double zr2 = zr * zr; double zi2 = zi * zi; zr = zr2 - zi2 + cr; zi = temp + temp + ci; if (zi2 + zr2 > BAILOUT) return i; if (i > MAX_ITERATIONS) return 0; } } int _tmain (int argc, _TCHAR* argv[]) { clock_t old,now; old=clock(); int x,y; for (y = -39; y < 39; y++) { printf("\n"); for (x = -39; x < 39; x++) { int i = mandelbrot(x/40.0, y/40.0); if (i==0) printf("*"); else printf(" "); } } printf ("\n"); now=clock(); double query_time = ((double)(now-old))/CLOCKS_PER_SEC; printf ("C Elapsed %0.2f\n", query_time); return 0; } 运行结果: * * * * * *** ***** ***** *** * ********* ************* *************** ********************* ********************* ******************* ******************* ******************* ******************* *********************** ******************* ******************* ********************* ******************* ******************* ***************** *************** ************* ********* * *************** *********************** * ************************* * ***************************** * ******************************* * ********************************* *********************************** *************************************** *** ***************************************** *** ************************************************* *********************************************** ********************************************* ********************************************* *********************************************** *********************************************** *************************************************** ************************************************* ************************************************* *************************************************** *************************************************** * *************************************************** * ***** *************************************************** ***** ****** *************************************************** ****** ******* *************************************************** ******* *********************************************************************** ********* *************************************************** ********* ****** *************************************************** ****** ***** *************************************************** ***** *************************************************** *************************************************** *************************************************** *************************************************** ************************************************* ************************************************* *************************************************** *********************************************** *********************************************** ******************************************* ***************************************** ********************************************* **** ****************** ****************** **** *** **************** **************** *** * ************** ************** * *********** *********** ** ***** ***** ** * * * * C Elapsed 0.25 完成相同功能的Forcal代码如下: mandelbrot(x, y : cr,ci,zi,zr,i,temp,zr2,zi2) = { cr = y - 0.5, ci = x, zi = 0.0, zr = 0.0, i = 0, (1).while { i ++, temp = zr * zi, zr2 = zr * zr, zi2 = zi * zi, zr = zr2 - zi2 + cr, zi = temp + temp + ci, if [zi2 + zr2 > 16, return (i)], if [i > 1000, return (0)] } }; main (:i,x,y,old,now) = { old=sys::clock(), y = -39, while{ y < 39, printff("\r\n"), x = -39, while{ x < 39, i = mandelbrot(x/40.0, y/40.0), which{ i==0, printff("*"), printff(" ") }, x++ }, y++ }, now=sys::clock(), printff("\r\nForcal Elapsed {1,r}\r\n",(now-old)/1000) };
运行时输出的图形与C程序相同,运行时间为:
Forcal Elapsed 1.078
从运行结果可看出,Forcal用的时间与c++相比,为1.078:0.25=4.312:1。
如果将Forcal代码中的自动变量改成模块变量,运算速度将加快:
mandelbrot(x, y :: cr,ci,zi,zr,i,temp,zr2,zi2) = { cr = y - 0.5, ci = x, zi = 0.0, zr = 0.0, i = 0, (1).while { i ++, temp = zr * zi, zr2 = zr * zr, zi2 = zi * zi, zr = zr2 - zi2 + cr, zi = temp + temp + ci, if [zi2 + zr2 > 16, return (i)], if [i > 1000, return (0)] } };main (::i,x,y,old,now) = { old=sys::clock(), y = -39, while{ y < 39, printff("\r\n"), x = -39, while{ x < 39, i = mandelbrot(x/40.0, y/40.0), which{ i==0, printff("*"), printff(" ") }, x++ }, y++ }, now=sys::clock(), printff("\r\nForcal Elapsed {1,r}\r\n",(now-old)/1000) };
运行时间为:0.922秒
这次,Forcal用的时间与c++相比,为0.922:0.25=3.688:1。
4.3 FcData效率测试
FcData是Forcal数据扩展动态库。以下比较大致体现了FcData的效率。
VC源程序:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
#include <time.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t old,now;
__int64 i,k;
__int64 *p;
char ch;
old=clock();
for(i=0,k=0;i<=1000000;i++)
{
p=new __int64[5];
p[3]=i; k=k+p[3];
delete[] p;
}
now=clock();
cout<<"vc++:"<<setprecision(20)<<k;
cout<<" 运行时间:"<<now-old<<" 即: "<<(double)(now-old)/CLOCKS_PER_SEC<<"秒"<<endl<<endl;
cin>>ch;
return 0;
}
VC运行结果:
vc++:500000500000 运行时间:218 即: 0.218秒
Forcal源程序:
i:NowFCDNum[10],SetFCDMax[2000000];
i:(:i,k,p,t)=
{ i=0,k=0,t=sys::clock(),
(i<=1000000).while
{
p=new[int_s,5],
p.[3].set(i), k=k+p.[3].get(),
delete[p],
i++
},
printff["结果:{1,i,},时间:{2,i}毫秒。\r\n",k,sys::clock()-t]
};
Forcal运行结果:
结果:500000500000,时间:1344毫秒。
在该例子中,Forcal的效率为VC的1344/218=6.17分之一, 因为FcData中new和delete这两个函数做了优化,故速度较快。若将new和delete这两个函数移到循环体的外边,Forcal的效率如下:
VC源程序:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
#include <time.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t old,now;
__int64 i,k;
__int64 *p;
char ch;
old=clock(); p=new __int64 [5];
for(i=0,k=0;i<=20000000;i++)
{
p[3]=i; k=k+p[3];
}
delete[] p; now=clock();
cout<<"vc++:"<<setprecision(20)<<k;
cout<<" 运行时间:"<<now-old<<" 即: "<<(double)(now-old)/CLOCKS_PER_SEC<<"秒"<<endl<<endl;
cin>>ch;
return 0;
}
VC运行结果:
vc++:200000010000000 运行时间:125 即: 0.125秒
Forcal源程序:
i:(:i,k,p,t)=
{ i=0,k=0,t=sys::clock(),p=new[int_s,5],
(i<=20000000).while
{
p.[3].set(i), k=k+p.[3].get(),
i++
},
delete[p],
printff["结果:{1,i,},时间:{2,i}毫秒。\r\n",k,sys::clock()-t]
};
Forcal运行结果:
结果:200000010000000,时间:2828毫秒。
在该例子中,Forcal的速度为VC的2828/125=22.62分之一。注意循环次数都增加到了20000000次。
4.4 矩阵运算效率测试
需要FcData、FcMath和FcSystem三个动态库的支持。
!using["math","sys"];
(:a,b,k,t0)=
oo{
a=rand[1000,1000], b=rand[1000,1000],
t0=clock(),
k=a*b, //矩阵乘
k[1,3:5,9].outm()
},
[clock()-t0]/1000;
4.5 网友bing_lonely的一个排列组合问题的Forcal实现
从一个各元素不同的偶数个元素数组(比如[1 2 3 4 5 6])中任取两个元素的组合,然后将这些所有两个元素的组合分成若干组,每组都能重新组成新数组,而这个新数组正好与原来数组相同,一共能排列成多少种,并一一列举出来。
比如数组1-6,[1 2 3 4 5 6],任意取两个元素一共有12,13,14,15,16,23,24,25,26,34,35,36,45,46,56十五种(6*5/2),将这十五个新元素可以不重复的组成5组新数组和原来一样,他们是:[12 34 56]、[13 25 46]、[14 26 35]、[15 24 36]、[16 23 45]——正好全部用完十五种不重复。
//需要FcData和XSLSF两个动态库的支持
i:a(::num)= num=12; //num为数的个数,必须为大于0的偶数
i:b(::控制)= 控制=6; //当得不到正确输出时,设置控制为更大的数,控制越大,运行时间约长;控制>0
i:c(::随机数种子)= 随机数种子=7; //当得不到正确输出时,改变随机数种子为其他大于等于1的奇数
i:insert(it,num,theline,me1,me2:j,k,t1,t2)={
j=0,k=num/2,
(j<k).while{
t1=it.get[theline,j,0],t2=it.get[theline,j,1],
if{t1==me1 | t1==me2 | t2==me1 | t2==me2, return(false)},
if{t1==0 & t2==0, it.set[theline,j,0:me1],it.set[theline,j,1:me2],return(true)},
j++
},
printff{"\r\n致命错误:程序在insert中工作出错!\r\n"}
};
i:ReplaceMe(it,num,line,index,me1,me2:i,k,t1,t2,me)={
i=0,k=num/2,me=0,
(i<k).while{
t1=it.get[line,i,0],t2=it.get[line,i,1],
if{t1==0, break()},
if[index==i, me=1, i++, continue()],
if{t1==me1 | t1==me2 | t2==me1 | t2==me2, return(false)},
i++
},
if[!me,return(false)],
t1=it.get[line,index,0],t2=it.get[line,index,1],
it.set[line,index,0:me1],it.set[line,index,1:me2],
me1=t1,me2=t2,
true
};
i:ReplaceLine(it,num,line,me1,me2:i)={
i=num/2-1,
(i).while{
if{!it.get[line,i,0], i-- ,continue()},
if{ReplaceMe(it,num,line,i,&me1,&me2),return(true)},
i--
},
false
};
rand(a,b,r)=XSLSF::rab1(itor(a),itor(b),&r).rtoi();
!using["io"];
i:writefile(s:f) =
{ f=new[file],
fopen[f,"组合数据.txt","wb+"],
fwrite[f,NULL,2,UTEXT],fwrite[f,s,s.FCDstrlen()],
fclose[f],
delete[f]
};
i:main(:i,j,k,ii,jj,kk,it,me1,me2,me_1,me_2,me,kkk,r,max,str:num,控制,随机数种子)={
it=new[int_s,num-1,num/2,2],str=new[string,num*num*2*10,EndType,""],
r=itor(随机数种子%(num-2)),
i=0,
(i<num-1).while{
j=0,
(j<num/2).while{
k=0,
(k<2).while{
it.set[i,j,k:0],
k++
},
j++
},
i++
},
/////////////////////////////////
me1=1,me=2,ii=0,kkk=0,
(me1<num).while{
me2=me++,
(me2<=num).while{
////////////////////////////
me_1=me1, me_2=me2, max=0,
(max<num*控制).while{
i=0,
(i<num-1).while{
if{insert[it,num,i,me_1,me_2],break()},
i++
},
if[i!=num-1,break()],
until{0,ReplaceLine[it,num,rand(0,num-2,&r),&me_1,&me_2]},
max++
},
if{max==num*控制,printff{"\r\n程序在main中工作出错![{1,i,-3}{2,i,3}]无法加入!",me_1,me_2}},
////////////////////////////
me2++
},
me1++
},
/////////////////////////////////
i=0,
(i<num-1).while{
printfs{"\r\n{1,i,3}: ",i+1,str},
j=0,
(j<num/2).while{
printfs{"[{1,i,-3}{2,i,3}] ",it.get[i,j,0],it.get[i,j,1],str},
j++
},
i++
},
writefile(str),
printff{"{1,s}\r\n\r\n",str},
delete[it],delete[str]
};
5 演示FcData中的例子
所有例子均可不加修改地在ForcalTest或ForcalDemo中运行,例子请参考fcdata.htm。
6 演示XSLSF中的例子
所有例子均可不加修改地在ForcalTest或ForcalDemo中运行,例子请参考xslsf.htm。
7 演示QuitFc32W.dll
QuitFc32W.dll是Forcal运行监视动态库,在任意可接受输入的窗口,按 Ctrl+Alt+Q(q) 键可以退出Forcal漫长的计算过程或者无限循环。
加载QuitFc32W.dll后,运行"while[1,1];"进入无限循环,然后按 Ctrl+Alt+Q(q) 键。
8 例子动态库
8.1 Example.dll
该库包含如下函数:
(1) [实数函数] SetRunTime():设置运行时间
该函数记录运行时间初值。该函数与GetRunTime()配合使用,由GetRunTime()获得运行时间。
该函数总是返回0。
(2) [实数函数] GetRunTime():获得运行时间
该函数在SetRunTime()之后使用,由GetRunTime()可以获得自执行SetRunTime()以来的运行时间。
例如:
SetRunTime();
(:i,k)=
{
i=0,k=0,
while{i<=1000000,k=k+i,i++},
k
};
GetRunTime()
(3) [实数函数] simp2[a,b,"Y1","Y2","z",eps]:变步长辛卜生二重积分
/ b / Y2(x)
| |
| | z(x,y) dxdy
| |
/ a / Y1(x)
eps为积分精度。
该函数返回的运行错误代码FcErr的意义如下:
FcErr=1:需要字符串参数指定表达式;FcErr=2:指定的表达式不存在;FcErr=3:不能对表达式的自变量重新赋值;FcErr=4:表达式的参数个数不符合要求;FcErr=5:精度必须大于0。
例如:
f1(x)=-sqrt[1-x*x];
f2(x)=sqrt[1-x*x];
f(x,y)=exp[x*x+y*y];
simp2[0,1,"f1","f2","f",0.00001]
8.2 FcConst.dll
该库向Forcal添加常量,添加的整数和实数常量如下:
Key_IntFor=1, Key_RealFor=2, Key_ComplexFor=3,
Key_IntFunction=4, Key_RealFunction=5, Key_ComplexFunction=6,
Key_IntArray=7, Key_RealArray=8, Key_ComplexArray=9,
Key_Str=10, Key_IntConst=11, Key_RealConst=12,
Key_ComplexConst=13
可以在整数和实数表达式中使用这些常量。例如:
i:Key_RealFunction;
r:Key_RealFunction;
9 由章毅明(hias_asia)先生提供的例子(可通过hias_asia@126.com与章毅明
先生联系)
9.1 Cantor表搜索算法的Forcal实现
Georg Cantor证明了有理数是可列的。他用下面这一张表来证明该命题:
1/1 |
1/2 |
1/3 |
1/4 |
1/5 |
... |
2/1 |
2/2 |
2/3 |
2/4 |
... |
|
3/1 |
3/2 |
3/3 |
... |
|
|
4/1 |
4/2 |
... |
|
|
|
5/1 |
… |
|
|
|
|
… |
|
|
|
|
|
我们为上表中的每一项编号:第1项是1/1,然后是1/2,2/1,3/1,2/2,……你的任务是求表中第N项的值。
要求从键盘读入若干个正整数,对于每一个数n(1<=n<=100000),输出Cantor表中相应的数(以表中实际的分数形式输出,不要约分)。输入0表示结束。样例如下:
样例输入
1
3
8
14
0
样例输出
1/1
2/1
2/3
2/4
#include
<iostream>
using namespace std;
int main()
{
int n;
while (cin >> n)
//
读入n
{
if (n == 0)
// n为0时退出
break;
int sum = 0;
// 所经过的数的数目
int i = 0;
// 第n个数在第i斜线上
while (sum < n)
// 直到经过的数不少于n
{
i++;
// 下一条斜线
sum += i;
}
if (i % 2 == 1)
// i是奇数
cout << sum -
n + 1 << '/' << n - sum + i << endl;
else
// i是偶数
cout << n -
sum + i << '/' << sum - n + 1 << endl;
}
return 0;
}
Forcal源代码:
i:Cantor(n:sum,i)={ // 读入n=1,3,8,14,0 if(n==0,return(0)), // n为0时退出 sum=0, // 所经过的数的数目 i=0, // 第n个数在第i斜线上 while{ sum<n, i++, // 下一条斜线 sum=sum+i }, if(i%2==1,printff("{1,i}/{2,i}\r\n",sum-n+1,n-sum+i).return()), // i是奇数 printff("{1,i}/{2,i}\r\n",n-sum+i,sum-n+1) // i是偶数 }; i:Cantor[1]; i:Cantor[3]; i:Cantor[8]; i:Cantor[14];
9.2 移动内存算法的Forcal实现
对于有k个元素的数组int a[k]={...};写一个不另外申请数组空间,但可以申请少许变量的高效算法将数组内容循环左移m位。
比如:int a[6]={1,2,3,4,5,6},循环左移3位得到结果{4,5,6,1,2,3}。
i:OutPoint(x,n:i)= i=0,while{i<n,printff["{1,i} ",get(x,i)],i++};
i:HCF(x,y:a,r,b)= //求最大公因数
{
a=x,b=y,r=a%b,
while(r>0,a=b,b=r,r=a%b),
return(b)
};
i:Carry(:i,start,p,hloc,step,pv,tmp,point:m,len,b)= //数组的区间移动
{
start=0,p=0,i=0,len=6,m=3,
point=new(int_s,6,EndType,1,2,3,4,5,6),
hloc=HCF(len,m),
step=len-m,
while{ i<hloc,
p=i,start=p,get(point,p,&pv),
until{
p=(step+p)%len,
tmp=pv,get(point,p,&pv),set(point,p,tmp),
p==start
},
i++
},
OutPoint(point,6),
delete[point]
};
9.3 插入排序法
i:OutPoint(x,n:i)= i=0,while{i<n,printff["{1,i} ",get(x,i)],i++}; i:(:i,n,a:x,y,k)={ a=new(int_s,5,EndType,1,2,4,5,0), OutPoint(a,5), x=3, k=0,n=4, while( k<n, get(a,k,&y), if(x<y,break()), k=k+1 ), printff["\r\n在位置{1,i}处插入{2,i}\r\n",k,x], i=n, while( i>k, get(a,i-1,&y), set(a,i,y), i=i-1 ), set(a,k,x), OutPoint(a,5), delete[a] };
9.4 删除指定数据
i:OutPoint(x,n:i)= i=0,while{i<n,printff["{1,i} ",get(x,i)],i++}; i:(:i,y,a:n,x,k)={ n=8,x=12,k=0, //x为欲删除的数组元素 a=new(int_s,8,EndType,1,4,7,9,12,14,23,56), while(k<n, //查找欲删除数组元素的位置 get(a,k,&y), if(y==x,break()), k=k+1 ), if(k>n,printff("找不到此数据!"),return(-1)), i=k+1, while(i<n, //将x后的数组元素后移 get(a,i,&y), set(a,i-1,y), i=i+1 ), set(a,n-1,0), OutPoint(a,8) }
版权所有© Forcal程序设计
2002-2010,保留所有权利
E-mail: forcal@sina.com
QQ:630715621
最近更新:
2010年10月16日