📄 compile_hss.pas
字号:
unit Compile_Hss;
//////////////////////////////////////////////////////////////////////////
// //
// 数学函数动态编译器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;
(*
//2002.8
简要声明:
任何用户使用本软件属于个人自愿选择,作者不会对本软件所引起的对用
户的任何形式的损失负责,作者也不承诺对本类的维护的服务义务。
本类可以自由拷贝和使用,但必须包含完整的代码和说明,任何修改和用
于商业化目的的行为都应该尽量与作者取得联系,并得到授权。
( E-Mail: HouSisong@263.net )
本类的编写目的只是在程序运行过程中能够多次的快速的执行用户输入的
数学表达式,程序优化的目标是速度和高精度,所以基本数据类型采用的是80
位浮点型,很多地方的处理是以速度为首要目标,这样在计算的正确性和错误
处理方面就有所损失。
比如:计算 (x*x+y*y)^0.5 写为 |y|*Sqrt(1+Sqr(x/y)),|x|<|y| 以
提高计算适应能力和正确性;
而作者采用的是Sqrt(sqr(x)+sqr(y)),因为做乘法会比除法运算快很多;
最近更新,列表如下:
*增加了布尔运算; 引入逻辑运算符和比较运算符 (使用参见详细说明)
逻辑常量 真 true =1
逻辑常量 假 false =0
逻辑运算 与 AND
逻辑运算 或 OR
逻辑运算 异或 XOR
逻辑运算 非 NOT
相等 =
不等于 <>
小于 <
大于 >
小于等于 <=
大于等于 >=
!标识符 PI 现在被当作系统常量 PI=3.1415926...
标识符 e 系统给它的默认值为2.718281828...但程序可以重新赋值,与PI不同
!现在给出一个运算符优先级表:
由高到低
() (包括各种函数)
^
* \ / mod
+ -
= <> < > <= >=
AND、OR、XOR (NOT 可以看作函数)
//2002.8
*)
(*
//2002.7-2002.8
最近做了一些修改,见下:
<<更新列表>>:
*做了一些优化,速度又加快了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) (向零取整)
*增加了表达式中对截断取整函数Ceil的支持, 可以写为:Ceil(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、Windows98、WindowsMe、Windows2000、WindowsXP。
//2002.5-2002.6
}
(*
<<详细说明>>:
0.支持数学函数表达式的编译执行;
1.支持带参数编译,参数默认值为0;运行前请赋值;
2.常数可以用科学计数法表示,如: -1.4E-4=-0.00014;
系统定义的常量: 圆周率 PI=3.1415926535897932384626433832795...
逻辑真 true=1
逻辑假 false=0
当标识符为e时,系统默认值为 自然数
即 e=2.7182818284590452353602874713527...
但它和PI不同,e可以重新赋值
3.使用多重括号并不会降低速度,特别是在不容易分清楚计算优先级的时候,请多使用括号;
4.表达式中函数名和参数名等不区分大小写;关键字中不允许插入空格等字符;
5.编译的文本长度几乎不受限制(只是受内存和编译时间等系统影响)
6.利用错误号功能可以将错误描述翻译为其他语言(给出了两个翻译例子:中文繁体BIG5码的错误描述和英文版的错误描述);
7.允许在表达式中使用注释(TCopmile.EnabledNote:=true;),注释写法为:
单行注释: 双斜杠// 开始到一行结束(即遇到回车换行符)
长段注释: '{'、'}' 或'/*'、'*/' 之间的部分
8.系统使用的标识符除去下面列出的函数名(包括别名)外还有 :
'PI'、'true'、'false'、'BooleanXX'、'Const_SYS_N' 、'Const_ff_SYS_x_N'和 'ff_SYS_N' 等,
自定义的参数名称请不要再次使用它们;
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')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -