📄 compile_calc.pas
字号:
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 + -