把文字转成可执行的数学公式(100)

  • 主题发起人 主题发起人 wlyft
  • 开始时间 开始时间
W

wlyft

Unregistered / Unconfirmed
GUEST, unregistred user!
我要做一个函数参数比如为X通过对X进行计算返回结果但对X进行计算的公式又是由用户定的,保存在一个字符型的变量里比如这个公式1-((1-X)/4)也有可能是(1-X)/7总之公式由用户定这种程序要怎么写?不知你们懂得我在说什么没有?
 
函数表达式你可以取得,通过对其中的X字符串进行替换,就变成了一个常量表达式,然后网上查找表达式的计算代码,例如baidu“表达式求值”,就可以了。
 
有控件的,你上网查一下。好象有个paser还是什么名字来着,记不清了,你查查看吧。
 
这个我直接用sql语句实现,让sql忙去
 
其实不难,亲自动手编了一个,保证原创.下面说下思路:不管一个表达式多复杂,它的形式都是: A op B在这里,暂且把A称为左操数,B称为右操作数,op称为操作符关键就是找出op,然后左右一分,分成A与B两部分左操作数和右操作数具体又可能有N层嵌套,弄个递归就行了,不用多考虑.//下面是完整源码,可直接运行,测试正确//我这里只考虑小括号,与+-*/四种运算符//再扩充一下,把每个运算编成一个函数,那谅更灵活了...unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Edit1: TEdit
//表达式,如: 1-((1-X)/4) Edit2: TEdit
//变量值,如: 5 Edit3: TEdit
//计算结果 Label1: TLabel
Label2: TLabel
Label3: TLabel
Button1: TButton
procedure Button1Click(Sender: TObject)
private { Private declarations } function CalFunc(const ExpText: string): string
public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm} { TForm1 }procedure TForm1.Button1Click(Sender: TObject);var ExpText, X, sResult: string;begin ExpText:= Edit1.Text
X:= Edit2.Text
//中英文修正(防止那些粗心大意的人) ExpText:= StringReplace(ExpText, '+', '+', [rfReplaceAll, rfIgnoreCase])
ExpText:= StringReplace(ExpText, '-', '-', [rfReplaceAll, rfIgnoreCase])
ExpText:= StringReplace(ExpText, '*', '*', [rfReplaceAll, rfIgnoreCase])
ExpText:= StringReplace(ExpText, '/', '/', [rfReplaceAll, rfIgnoreCase])
ExpText:= StringReplace(ExpText, ' ', '', [rfReplaceAll, rfIgnoreCase])
ExpText:= StringReplace(ExpText, ' ', '', [rfReplaceAll, rfIgnoreCase])
//替换变量 ExpText:= StringReplace(ExpText, 'X', X, [rfReplaceAll, rfIgnoreCase])
//计算 sResult:= CalFunc(ExpText)
Edit3.Text:= sResult
if sResult = '' then ShowMessage('表达式错误');end;function TForm1.CalFunc(const ExpText: string): string;var i, Count: integer
S, S1, S2: string
v, v1, v2: Double;begin result:= ''
S:= ExpText
while (Length(S) > 1) and (S[1] = '(') and (S[Length(S)] = ')') do begin Delete(S, 1, 1)
Delete(S, Length(S), 1)
end
if TryStrToFloat(S, v) then begin result:= S
exit
end
S1:= ''
S2:= ''
Count:= 0
for i:= 1 to Length(S) do begin if S = '(' then inc(Count) else if S = ')' then dec(Count) else if S in ['+', '-', '*', '/'] then begin if Count = 0 then begin S1:= Copy(S, 1, i - 1)
S2:= Copy(S, i + 1, Length(S))
S1:= CalFunc(S1)
S2:= CalFunc(S2)
if TryStrToFloat(S1, v1) and TryStrToFloat(S2, v2) then begin if S = '+' then result:= FloatToStr(v1 + v2) else if S = '-' then result:= FloatToStr(v1 - v2) else if S = '*' then result:= FloatToStr(v1 * v2) else if S = '/' then result:= FloatToStr(v1 / v2)
end
exit
end
end
end;end;end.
 
CalFunc('2*2+3') 计算出来为10,没考虑+-*/的计算先后顺序吧?
 
我想先用 chbqq 的方法试试 ,但想要看个列子
 
抄袭djrj代码:function TForm1.CalFunc(const ExpText: string): string;var SQL:String
Query:TQuery
//你也可以在界面上特地放置一个querybegin //中英文修正(防止那些粗心大意的人) SQL:= StringReplace(ExpText, '+', '+', [rfReplaceAll, rfIgnoreCase])
SQL:= StringReplace(SQL, '-', '-', [rfReplaceAll, rfIgnoreCase])
SQL:= StringReplace(SQL, '*', '*', [rfReplaceAll, rfIgnoreCase])
SQL:= StringReplace(SQL, '/', '/', [rfReplaceAll, rfIgnoreCase])
SQL:= StringReplace(SQL, ' ', '', [rfReplaceAll, rfIgnoreCase])
SQL:= StringReplace(SQL, ' ', '', [rfReplaceAll, rfIgnoreCase])
//替换变量 SQL:= StringReplace(SQL, 'X', X, [rfReplaceAll, rfIgnoreCase])
// Query:=TQuery.Create
Query.sql.text:=Format('Select %s from 一个只有一条记录的表',[SQL])
Query.databasename:= try Query.Open
except Query.free
showmessage('表达式非法:'+ExpText)
Abort
end
Result:=Query.Fields[0].asfloat
Query.free;end;
 
网上找到好方法了,嘻嘻uses ComObj ..... function Eval(expStr: string): string
var js: OleVariant
begin js := CreateOleObject('ScriptControl')
js.Language := 'JavaScript'
Result := js.Eval(expStr)
js := Unassigned
end;
 
看看编译原理里就有的 逆波兰式 好像是这个
 
最简单的方法:用数据库比如说:(以sql server为例)declare @calc nvarchar(1000), @sql nvarchar(1000)set @calc='(1+2+3)/(4+5)'set @sql='select '+@calc+' as calc'exec sp_executesql @sql前台只要查询calc这个字段的值就可以了。
 
to:wlyft果然好用,学习了!多谢
 
wlyft 好方法,我试过了。OK.收藏。
 
多人接受答案了。
 
后退
顶部