如何简化计算式 ( 积分: 100 )

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

white_shark

Unregistered / Unconfirmed
GUEST, unregistred user!
比如:
1+2*(1*0+2+0)*0+(3+cos(90))-1/2=3.5
简化后: 1+3-1/2=3.5
即把为 0 的去掉 ,还要计算正确.
 
都不用去零的,直接算就是了:
var
vScript: Variant;

vScript := CreateOleObject('ScriptControl');
vScript.Language := 'JavaScript';
str := vScript.Eval(str);
 
呵呵,楼主这题出的蛮阴的嘛,陷阱多多啊。
除了cos,还要支持哪些函数啊,全部列出来才好编程序。
还有,等式右边仅仅是数值结果还是也可能是表达式?
 
函数一般的都有吧!等式右边是结果.
请多多指教!!!
 
“函数一般的都有吧!”等于没回答哎!
算了,做个仅支持cos的版本吧,理解了加其他函数很容易的,不过函数多了就不能用排列if语句的办法了。
另外,没做错误处理,没做仔细测试,有什么小Bug自己改改吧。能改就说明理解了。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

type
TTree = ^TNode;
TNode = record
op: string;
Value: Double;
LeftChild, RightChild: TTree
end;

TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function FindLastOpPos(s: string): Integer;
var
i: Integer;
Count: Integer;
begin
Result:=0;
Count:=0;
for i:=Length(s) downto 1 do
case s of
'(' : Dec(Count);
')' : Inc(Count);
'+', '-': if Count=0 then
begin
Result:=i;
Exit
end;
'*', '/': if (Count=0) and (Result=0) then
Result:=i
end
end;

procedure DestroyTree(Root: TTree);
begin
if Root=nil then
Exit;
if Root^.LeftChild<>nil then
DestroyTree(Root^.LeftChild);
if Root^.RightChild<>nil then
DestroyTree(Root^.RightChild);
Dispose(Root)
end;

function MakeTree(s: string): TTree;
var
Len: Integer;
p: Integer;
begin
if s='' then
Result:=nil
else
begin
Len:=Length(s);
if (s[1]='(') and (s[Len]=')') then
Result:=MakeTree(Copy(s, 2, Len-2))
else
begin
New(Result);
p:=FindLastOpPos(s);
if p>1 then
begin
Result^.op:=s[p];
Result^.LeftChild:=MakeTree(Copy(s, 1, p-1));
Result^.RightChild:=MakeTree(Copy(s, p+1, Len-p))
end
else if Pos('cos', LowerCase(s))=1 then
begin
Result^.op:='cos';
Result^.LeftChild:=MakeTree(Copy(s, 5, Length(s)-5));
Result^.RightChild:=MakeTree('0')
end
else
begin
Result^.Op:=s;
Result^.LeftChild:=nil;
Result^.RightChild:=nil
end
end
end
end;

procedure CalculateTree(Root: TTree);
var
a, b: Double;
begin
if (Root^.LeftChild=nil) and (Root^.RightChild=nil) then
Root^.Value:=StrToFloat(Root^.op)
else
begin
CalculateTree(Root^.LeftChild);
CalculateTree(Root^.RightChild);
case Root^.op[1] of
'+': Root^.Value:=Root^.LeftChild^.Value+Root^.RightChild^.Value;
'-': Root^.Value:=Root^.LeftChild^.Value-Root^.RightChild^.Value;
'*': Root^.Value:=Root^.LeftChild^.Value*Root^.RightChild^.Value;
'/': Root^.Value:=Root^.LeftChild^.Value/Root^.RightChild^.Value;
'c': Root^.Value:=Cos(Root^.LeftChild^.Value*Pi/180)
end
end
end;

function IsZero(const Value: Double): Boolean;
begin
Result:=Abs(Value)<1e-5
end;

function GetResult(Root: TTree): string;
var
s1, s2: string;
begin
if Root=nil then
Result:=''
else if IsZero(Root^.Value) then
Result:='0'
else if (Root^.LeftChild=nil) and (Root^.RightChild=nil) then
Result:=Root^.op
else
begin
s1:=GetResult(Root^.LeftChild);
s2:=GetResult(Root^.RightChild);
case Root^.op[1] of
'+': if s1='0' then
Result:=s2
else if s2='0' then
Result:=s1
else
Result:=s1+'+'+s2;
'-': if s2='0' then
Result:=s1
else
begin
if (Root^.RightChild^.op[1] in ['+', '-']) then
s2:='('+s2+')';
if s1='0' then
Result:='(-'+s2+')'
else
Result:=s1+'-'+s2
end;
'*': begin
if (Root^.LeftChild^.op[1] in ['+', '-']) then
s1:='('+s1+')';
if (Root^.RightChild^.op[1] in ['+', '-']) then
s2:='('+s2+')';
Result:=s1+'*'+s2
end;
'/': begin
if (Root^.LeftChild^.op[1] in ['+', '-']) then
s1:='('+s1+')';
if (Root^.RightChild^.op[1] in ['+', '-', '*', '/']) then
s2:='('+s2+')';
Result:=s1+'/'+s2
end;
'c': Result:='cos('+s1+')'
end
end
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Root: TTree;
s: string;
p: Integer;
begin
s:=Edit1.Text;
p:=Pos('=', s);
Root:=MakeTree(Copy(s, 1, p-1));
CalculateTree(Root);
Edit2.Text:=GetResult(Root)+Copy(s, p, Length(s)-p+1);
DestroyTree(Root)
end;

end.
 
要考编译原理吗
 
to 楼上的:考编译原理没这么阴,编译原理的要求也就是求值或者是逆波兰编码,完全可以省略程序中的GetResult过程。
 
LeeChange 大侠似乎好久没出现了,谢谢多年前解答的问题 [:D]
 
LeeChange大虾的治学态度令人敬佩,不过有时走走捷径未尝不可,呵呵,下面的代码编译通过:
procedure TForm1.Button1Click(Sender: TObject);
var
vScript: Variant;
ss: string;
begin
vScript := CreateOleObject('ScriptControl');
vScript.Language := 'vbScript';
ss := vScript.Eval('1+2*(1*0+2+0)*0+(3+cos(90))-1/2');
showmessage(ss);
end;

不过算出来是3.0519。不是是原先楼主计算有误还是vb脚本计算出错?就没仔细看了
注意,需uses comobj 单元。
 
多谢,问题一解决.
 

Similar threads

回复
0
查看
1K
不得闲
D
回复
0
查看
926
DelphiTeacher的专栏
D
D
回复
0
查看
718
DelphiTeacher的专栏
D
后退
顶部