欢迎访问 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
   
};
   
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实现

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/22/13/12/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日