⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compile_calc.pas

📁 进销存·完整的·有数据库的·非常完整·只得参考
💻 PAS
📖 第 1 页 / 共 3 页
字号:
unit Compile_Calc;

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//      数学函数动态编译器TCompile类    作者:侯思松  2002.4-2002.8。    //
//                      (包括数学函数和定积分函数)                      //
//           有改进意见或发现任何错误请转告我,本人不胜感激。            //
//                       E-Mail:HouSisong@263.net                       //
//                      (  转载时请保留本说明:)  )                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<///
///  <<功能简介>>:                                                             ///
///     TCompile可以在程序运行过程中动态完成数学函数表达式字符串的编译执行,    ///
///  (可以带参数,定积分;动态生成机器码执行,不是解释执行)执行速度超快!!!        ///
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>///

{
  <<使用方法>>:
 var
   Compilation : TCompile; // 声明Compilation为数学函数动态编译器TCompile类
 begin
     Compilation:=TCompile.Create; //创建类
   try
     Compilation.SetText(str);   //str为要 求值的数学表达式字符串,比如str:='x+sin(y*PI/2)*3'
                                 //(可以带有未知数参数);
     ......
     //如果有参数,可以获得参数地址,并赋值 (默认值为0)
     //如: PExtendedX:=Compilation.GetParameterAddress('x');
     //如: PExtendedY:=Compilation.GetParameterAddress('y');
     //    if not(PExtendedX=nil) then PExtendedA^:=1.5;
     //    if not(PExtendedY=nil) then PExtendedA^:=0.5;
     //也可以一次获得所有的参数列表:Compilation.GetParameterList(PList);
     ......
     xValue:=Compilation.GetValue(); //获得表达式的值,
                                     //可以多次改变参数值并多次调用(如放在循环中),这样才能显示出效率:)
     ......
   finally
     Compilation.Free;     //释放类
   end;
 end;
}

interface

uses SysUtils, Forms, Classes, Math, Variants;

(*
   最近做了一些修改,见下:

 <<更新列表>>:

   *做了一些优化,速度又加快了25%! 现在编译代码的执行效率更高。

   *为了减少TCompile类运行时占用的内存空间,而采用了动态的内存空间申请方式,
    并且对能编译的文本长度几乎不再限制(只是受内存和编译时间等系统影响),
    作者曾经测试过上百K的表达式编译和运算:);

   *增加了错误号,以利于将错误描述翻译为其他语言(给出了两个翻译例子:中文繁体BIG5码的错误描述和英文版的错误描述);
   *现在允许在表达式中使用注释(TCopmile.EnabledNote:=true;默认为false),注释写法为:
       单行注释:  双斜杠// 开始到一行结束(即遇到回车换行符)
       长段注释:  '{'、'}' 或'/*'、'*/' 之间的部分

   !!!关键字中不允许插入空格等字符;
       以前版本 如 "Si n (P I/2)" 可以正常运行 等于"Sin(PI/2)", "d 45"被认为是"d45",现在不再允许!

   !!!为了避免混乱,参考数学手册重新对表达式中的数学函数名称和别名做了修订,使用过以前版本的请注意一下;

   *重新考虑了浮点状态标志中RC场的值对各种利用了取整运算的函数的影响

   !!!纠正错误:
       常数运算优化时对 求余函数'Mod'的优化错误   如错误: 10 mod 7=9 !  应该为: 10 mod 7=3
       原来代码:  ConstdValue:=T_PTrueOld.dValue-Trunc(T_PTrueOld.dValue/T_PTrueNow.dValue)
       改为:      ConstdValue:=T_PTrueOld.dValue-Trunc(T_PTrueOld.dValue/T_PTrueNow.dValue)*T_PTrueNow.dValue

   !!!纠正错误:
       常数运算优化时对 反正切2函数'ArcTan2'的优化错误
       原来代码:  ConstdValue:=math.ArcTan2(T_PTrueNow.dValue,T_PTrueOld.dValue)
       改为:      ConstdValue:=math.ArcTan2(T_PTrueOld.dValue,T_PTrueNow.dValue)

   !!!纠正错误:
       常数运算优化时对 取整函数'Int'的优化错误   如错误: Int(-1.5)=-1 ! 应该为: Int(-1.5)=-2  (RC场取整方式造成的)
       原来代码:  ConstdValue:=Trunc(T_PTrueNow.dValue)
       改为:      xTemp:=Trunc(T_PTrueNow.dValue);
                  if Frac(T_PTrueNow.dValue) <0 then
                    xTemp:=xTemp-1;
                  ConstdValue:=xTemp;

   !!!纠正错误:
       修正了编译子函数 整除函数TCompile.F_DivE();  错误: c:=-10; c\7=-2 ! 应该为: c\7=-1  (RC场取整方式造成的)
       (完全改写 具体修改略)

   *增加了表达式中对截断取整函数Trunc的支持, 可以写为:Trunc(x)   (向零取整)
   *增加了表达式中四舍五入取整函数Round的支持, 可以写为:Round(x)   (四舍五入取整)
       注: Int(x)或Floor(x)函数值为不大于x的最大整数  (向负无穷大取整)

   *增加了表达式中对随机函数Random的支持, 可以写为:Random(x)、RND(x)、Rand(x)
       请使用"TCopmile.SetRandomize();"函数初始化随机函数

   *增加了表达式中对余切函数Cot的支持;
   *增加了表达式中对正割函数Sec的支持;
   *增加了表达式中对余割函数Csc的支持;
   *增加了表达式中对反余切函数ArcCot的支持;
   *增加了表达式中对反正割函数ArcSec的支持;
   *增加了表达式中对反余割函数ArcCsc的支持;

   *增加了表达式中对双曲余切函数CotH的支持;
   *增加了表达式中对双曲正割函数SecH的支持;
   *增加了表达式中对双曲余割函数CscH的支持;
   *增加了表达式中对反双曲余切函数ArcCotH的支持;
   *增加了表达式中对反双曲正割函数ArcSecH的支持;
   *增加了表达式中对反双曲余割函数ArcCscH的支持;

   *增加了表达式中对斜边函数Hypot的支持;
   *增加了表达式中对求倒数函数Rev的支持;

   次方运算现在可以写为:  x**y、x^y、Power(x,y)
   求余运算现在可以写为:  x%y 、x Mod y 、Mod(x,y)

  ------------------------------------------------------------------------------

   不知道本TCompile类单元在Linux环境下能不能用,作者没有试过,希望有大虾帮忙告知:)

   希望大家能帮忙测试一下本编译类,特别是当把它用到了某些关键性计算事务中时,这
非常关键!一个小的bug就足以致命!!!您可以就某些方面进行测试,甚至是其中的一个函数,
然后把发现的错误的具体情况告诉我,以便修改;测试时没有发现错误把测试情况告诉我,
万分感谢!!!

   我的 E-Mail: HouSisong@263.net    QQ: 9043542

  ------------------------------------------------------------------------------

//2002.7-2002.8
*)

{
    作者以前写过一个解释执行数学函数表达式的程序,因为最近使用到而解释执行太慢了满足不了要求,
所以编写了本编译类单元(数学函数动态编译器TCompile类)。
    TCompile可以完成数学函数表达式的动态编译和执行(动态生成机器码),编译后的执行
速度比以前解释执行的版本快了5000倍左右!在多次执行和表达式复杂情况下,TCompile在程序
执行过程中动态编译的函数执行速度与Delphi6在程序设计阶段静态编译后的函数执行速度
相当,在有些情况下甚至快很多(注:测试时速度比一般在35%-180%之间,表达式简单的时候类TCompile
的调用开销太大,影响了测试结果,但只从代码实际执行部分来看,TCompile比Delphi6编译的快很多!!!)。
    测试环境包括:Windows95、WindowsMe、Windows2000、WindowsXP。

//2002.5-2002.6
}

(*

<<详细说明>>:

1.支持带参数编译,参数默认值为0;运行前请赋值;

2.常数可以用科学计数法表示,如: -1.4E-4=-0.00014;
  系统定义的常数:  圆周率 PI=3.1415926535897932384626433832795
                   自然数  e=2.7182818284590452353602874713527
                   (允许重新赋值)

3.使用多重括号并不会降低速度,特别是在不容易分清楚计算优先级的时候,请多使用括号;

4.表达式中函数名和参数名等不区分大小写;关键字中不允许插入空格等字符;

5.编译的文本长度几乎不受限制(只是受内存和编译时间等系统影响)

6.利用错误号功能可以将错误描述翻译为其他语言(给出了两个翻译例子:中文繁体BIG5码的错误描述和英文版的错误描述);

7.允许在表达式中使用注释(TCopmile.EnabledNote:=true;),注释写法为:
       单行注释:  双斜杠// 开始到一行结束(即遇到回车换行符)
       长段注释:  '{'、'}' 或'/*'、'*/' 之间的部分

8.系统使用的标识符除去下面列出的函数名(包括别名)外还有 :
  'Const_SYS_N' 、'Const_ff_SYS_x_N'和 'ff_SYS_N' ,自定义的参数名称请不要再次使用它们;
  如果参数名称为 'PI' 和 'e'  ,那默认值见上面,但这只是它的默认值,程序中可以重新赋值;

9.支持的函数:

  这里的实数域为:  R' ,  R'约为 (-1.1E+4932,-3.6E-4951) and [ 0 ] and (+3.6E-4951,+1.1E+4932)
  当实数属于(+-3.6E-4951,0) 时认为实数等于0
  没有特别说明的变量取值范围为实数域 R'

(函数计算的结果和中间结果也不能超出实数域 R')

算符(函数)名称       书写格式和变量取值范围                       例子(说明)

+        加法        x+y     或者: Add(x,y)                       3.5+5=8.5
-        减法        x-y     或者: Sub(x,y)                       8-3=5
*        乘法        x*y     或者: Mul(x,y)                       2*3=6
/        除法        x/y     或者: Div(x,y)   ; y<>0              3/2=1.5
\        整除        x\y     或者: DivE(x,y)  ; y<>0              25\10=2
Mod      求余        x Mod y   或者: x%y、Mod(x,y) ; y<>0         14 Mod 5=4
^        指数        x^y     或者:  Power(x,y)、x**y              2^3=8
                     ; x<0时,y必须为整数
                     ; x=0时,y>0

Max      最大值      Max(x,y)                                     Max(3,4)=4
Min      最小值      Min(x,y)                                     Min(3,4)=3
Sqr      平方        Sqr(x)                                       Sqr(3)=9  //注意平方和开方的函数名称
Sqrt     开方        Sqrt(x)    ; x>=0                            Sqrt(3)=1.73205080756888

Sin      正弦        Sin(x)                                       Sin(pi/6)=0.5
Cos      余弦        Cos(x)                                       Cos(0)=1
Tan      正切        Tan(x)   或者: tg(x)                         Tan(pi/4)=1
ArcSin   反正弦      ArcSin(x)    ; -1<=x<=1                      ArcSin(1)=1.5707963267949=pi/2
ArcCos   反余弦      ArcCos(x)    ; -1<=x<=1                      ArcCos(0)=1
ArcTan   反正切      ArcTan(x) 或者:  Arctg(x)                    ArcTan(1)=0.785398163397448=pi/4
ArcTan2  反正切2     ArcTan2(y,x) 或者:  Arctg2(y,x)              ArcTan2(2,1)=1.10714871779409
                     ;y为纵坐标、x为横坐标
Cot      余切        Cot(x)    或者: Ctg(x)   ;x<>0               Cot(x)=1/Tan(x)
Sec      正割        Sec(x)                                       Sec(x)=1/Cos(x)
Csc      余割        Csc(x)                   ;x<>0               Csc(x)=1/Sin(x)
ArcCot   反余切函数  ArcCot(x) 或者: ArcCtg(x)   ;x<>0            ArcCtg(x)=ArcTan(1/X)  //Delphi6 误为 ArcCtg(x)=Tan(1/X)  !
ArcSec   反正割函数  ArcSec(x)              ;|x|>=1               ArcSec(x)=ArcCos(1/X)  //Delphi6 误为 ArcSec(x)=Cos(1/X)  !
ArcCsc   反余割函数  ArcCsc(x)              ;|x|>=1               ArcCsc(x)=ArcSin(1/X)  //Delphi6 误为 ArcCsc(x)=Sin(1/X)  !

Exp      自然指数    Exp(x)                                       Exp(2)=e*e=e^2
Ln       自然对数    Ln(x)                    ; x>0               Ln(e)=1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -