欢迎访问 Forcal程序设计

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
};
G etRunTime()

(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实现

# Cantor 表

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日