• 全部
  • C#综合技术
  • C#互联网桌面应用
  • AppLauncher
  • WinForm&WPF
  • C#开发新技术
  • 问答

求一算法:

jastion 2004-10-25 07:58:32
求一算法:

string str = "5 + 6 + 7 " ;
//根據str進行運算,即得到如下運算式:
float num = 5 + 6 + 7 ;

string str = "5 - (6 + 7) " ;
//根據str進行運算,即得到如下運算式:
float num = 5 - (6 + 7);

string str = "5 * (6 + 7) " ;
//根據str進行運算,即得到如下運算式:
float num = 5 * (6 + 7) ;

請教如何到到運算式:
...全文
83 点赞 收藏 7
写回复
7 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
happyjun2000 2004-10-26
有和你同样的帖子,你看一下
http://www.yestar2000.com/TechCenter/1410/TC_16048.htm
mfc下通过编译可以运行,有表达式纠错功能。
运算符号有+ - * / ^ sin() cos() tan() ln() () 任意的组合或嵌套

class supermath{
public:
int deadline;
CString errormsg;
CString expstr;
CString thesign;
float runstr(CString,int);
int isdigits(CString);
void xtrim(CString*);
void prerun(CString*);
CString getresult();
void loadexp(CString);
};

void supermath::loadexp(CString str){
expstr=str;
}

int supermath::isdigits(CString str)
{
int i,is=1;
char *t=str.GetBuffer(str.GetLength());
for (i=0;i<(int)strlen(t);i++)
if (!((*(t+i)>='0' && *(t+i)<='9') || *(t+i)=='.' || (*(t+i)=='-' && i==0))) is=0;
return is;
}

void supermath::xtrim(CString *str)
{
char *t=str->GetBuffer(str->GetLength());
int level=0,isdotrim=1;
for(int i=0;i<(int)strlen(t)-1;i++)
{
if (*(t+i)=='(') level++;
if (*(t+i)==')') level--;
if (level==0) isdotrim=0;
}
if ((isdotrim)&&strlen(t)>1)
{
*str=str->Mid(1,str->GetLength()-2);
xtrim(str);
}
}

void supermath::prerun(CString *str){
int level=0,i;
for(i=0;i<str->GetLength();i++){
if (str->Mid(i,1)=='(') level++;
if (str->Mid(i,1)==')') level--;
}
if (level!=0) errormsg="括号请成对!";
str->Replace("tg","tan");
}

float supermath::runstr(CString str,int maxtime)
{
float midvar;
int i,j,level;
if (errormsg!="") return 2;
if (maxtime>deadline) {
errormsg="expression fleat!!";
return 2;
}
xtrim(&str);
if (isdigits(str)) return (float)atof(str.GetBuffer(str.GetLength()));
else {
char *exp=str.GetBuffer(str.GetLength());
char *sign=thesign.GetBuffer(str.GetLength());
for(i=0;i<10;i++){
level=0;
for(j=0;j<str.GetLength()-1;j++)
{
if (*(exp+j)=='(') level++;
if (*(exp+j)==')') level--;
if (str.Mid(j,1)==thesign.Mid(i,1) && level==0) {
CString str1=str.Mid(0,j);
CString str2=str.Mid(j+1);
switch (*(sign+i))
{
case '+':
return runstr(str1,maxtime+1)+runstr(str2,maxtime+1);break;
case '-':
if (str1=="") midvar=0; else midvar=runstr(str1,maxtime+1);
return midvar-runstr(str2,maxtime+1);break;
case '*':
return runstr(str1,maxtime+1)*runstr(str2,maxtime+1);break;
case '/':
midvar=runstr(str2,maxtime+1);
if (midvar==0) {errormsg+=" '/0'形错误 位置:‘"+str+"’<-err.. "; return 2;}
return runstr(str1,maxtime+1)/midvar; break;
case '^':
midvar=(float)pow(runstr(str1,maxtime+1),runstr(str2,maxtime+1));
if ((midvar+1)==midvar) { errormsg+=" '-x^0.5'形错误 位置:‘"; errormsg+=str; errormsg+="’<-err.. "; return 2; }
return midvar; break;
case 'i':
return (float)sin(runstr(str2.Mid(1),maxtime+1));break;
case 'c':
return (float)cos(runstr(str2.Mid(2),maxtime+1));break;
case 't':
midvar=(float)tan(runstr(str2.Mid(2),maxtime+1));
if ((midvar+1)==midvar) {errormsg+=" 'tan(pi/2)'形错误 位置:‘"+str+"’<-err.. "; return 2;}
return midvar; break;
case 'b':
return (float)fabs(runstr(str2.Mid(1),maxtime+1));break;
case 'l':
midvar=runstr(str2.Mid(1),maxtime+1);
if (midvar<=0) {errormsg+=" 'ln-'形错误 位置:‘"+str+"’<-err.. "; return 2;}
return (float)log(midvar); break;
default:
errormsg+=" 内部未知错误!";
}
}
}
}
}
errormsg+="含有未知运算符 位置:‘"+str+"’<-err.. ";
return 2;
}


CString supermath::getresult()
{
deadline=10;
errormsg="";
thesign="+-/*^ictbl";
errormsg="";
CString str;

prerun(&expstr);
str.Format("%f",runstr(expstr,1));
if (errormsg=="") return str; else return errormsg;
}
回复
jastion 2004-10-26
哈哈3Q大家的光臨,問題解決了,
10多行代碼。
回复
Korny 2004-10-25
表达算的计算,看看数据结构就行了,我以前写的一个计算表达式算法,没有完全对表达式进行合法验证,这你用状态图解决。

class StackChar{
private static char stack_data[];
private static int stack_ptr;

StackChar(int size)
{
stack_data=new char[size];
stack_ptr=-1;
}

public char Pop()
{
if(stack_ptr==-1)
return '0';
else
return stack_data[stack_ptr--];
}

public int Push(char push_this)
{
if(stack_ptr>=stack_data.length)
{return 0;}
else
{
stack_data[++stack_ptr]=push_this;
return 1;
}
}

public boolean IsEmpty()
{
if (stack_ptr==-1)
{ return true;}
else
{return false;}
}

public char GetTop()
{

if(stack_ptr==-1)
{return '0';}
else
{return stack_data[stack_ptr];}
}
}//end StackChar


class StackFloat{
private static float stack_data[];
private static int stack_ptr;

StackFloat(int size)
{
stack_data=new float[size];
stack_ptr=-1;
}

public float Pop()
{
if(stack_ptr==-1)
return '0';
else
{

return stack_data[stack_ptr--];
}
}

public int Push(float push_this)
{
if(stack_ptr>=stack_data.length)
{return 0;}
else
{
stack_data[++stack_ptr]=push_this;

return 1;
}
}


public boolean IsEmpty()
{
if (stack_ptr==-1)
{ return true;}
else
{return false;}
}



}//end StackFloat





public class Exp{

final static float a=3;
final static float b=7;
final static float c=14;
final static float d=2;
final static float e=3;
final static float f=4; //表达式中的字符与之相应的值到ToFloat方法中修改

public static void main(String args[]){

Exp exp=new Exp();
String op_str="a+(b+((c/d-e))*f";
op_str+="#";

System.out.println("要运算的表达式为:"+op_str);
System.out.println("其逆波兰式为:"+ new String(exp.GetNiBoLa(op_str))); //把表达式转化为逆波兰式

System.out.println("其值为:"+exp.GetValue(exp.GetNiBoLa(op_str)));//得到表达式的值



}//main

private boolean dx(char cha,char chb)
{
int ap=0;
int bp=0;

switch(cha)
{
case '#':
ap=1;
break;
case '(':
ap=2;
break;
case '+':
ap=3;
break;
case '-':
ap=3;
break;
case ')':
ap=4;
break;
case '*':
ap=4;
break;
case '/':
ap=4;
break;

}

switch(chb)
{
case '#':
bp=1;
break;
case '(':
bp=2;
break;
case '+':
bp=3;
break;
case '-':
bp=3;
break;
case ')':
bp=4;
break;
case '*':
bp=4;
break;
case '/':
bp=4;
break;

}


if (ap>=bp)
return true;
else
return false;
}//func dx

private boolean InOP(char ch)
{
char OP[]={'#','(','+','-',')','*','/'};
for(int i=0;i<7;i++)
{
if(OP[i]==ch)
return true;

}
return false;

}

private float OP(float a,char op,float b)
{
float Result=0;
switch (op)
{ case '+':
Result=a+b;
break;
case '-':
Result=a-b;
break;
case '*':
Result=a * b;
break;
case '/':
Result=a/b;
break;
}

return Result;

}


private char[] GetNiBoLa(String exp_str)
{

StackChar s=new StackChar(100);
Exp e=new Exp();
char exp_new[]=new char[100];
int k=0;
int i=0;
char ch,c;
boolean b_temp;
s.Push('#');



ch=exp_str.charAt(i++);

while(!s.IsEmpty()){

if(! e.InOP(ch))
{ exp_new[k++]=ch;}
else{
switch(ch){
case '(':s.Push(ch);break;
case ')':{
c=s.Pop();
while(c!='(')
{exp_new[k++]=c;
c=s.Pop();
}
break;
}
default:
{
c=s.GetTop();

if(e.dx(c,ch))
{ b_temp=true; s.Pop();}

else
b_temp=false;



while(!s.IsEmpty() && b_temp){
exp_new[k++]=c;
c=s.GetTop();

if(e.dx(c,ch))
{ b_temp=true;s.Pop();}
else
b_temp=false;




}
if (ch!='#') s.Push(ch); //优先数大于栈顶的入栈
break;
}//default
}//switch
}//else



if (ch!='#')
{ ch=exp_str.charAt(i++);
//exit while
}//while

}
return exp_new;
}//GetNiBoLa


private float GetValue(char str_nibo[])
{
float aa,bb;

String str_NiBo=new String(str_nibo).trim();

StackFloat stack_Opnd=new StackFloat(100);
Exp ee=new Exp();



for (int i=0;i<str_NiBo.length();i++)
{



switch (str_NiBo.charAt(i))
{
case '+':
bb=stack_Opnd.Pop();aa=stack_Opnd.Pop();
stack_Opnd.Push(ee.OP(aa,'+',bb));
break;
case '-':
bb=stack_Opnd.Pop();aa=stack_Opnd.Pop();
stack_Opnd.Push(ee.OP(aa,'-',bb));
break;
case '*':
bb=stack_Opnd.Pop();aa=stack_Opnd.Pop();
stack_Opnd.Push(ee.OP(aa,'*',bb));
break;
case '/':
bb=stack_Opnd.Pop();aa=stack_Opnd.Pop();
stack_Opnd.Push(ee.OP(aa,'/',bb));
break;

default:
{

stack_Opnd.Push(ee.ToFloat(str_NiBo.charAt(i)));
break;
}
}

}//




return stack_Opnd.Pop();




}//GetValue


private float ToFloat(char chThis)
{
float Result=0;
switch(chThis){
case 'a':
Result=a;
break;
case 'b':
Result=b;
break;
case 'c':
Result=c;
break;
case 'd':
Result=d;
break;
case 'e':
Result=e;
break;
case 'f':
Result=f;
break;
}

return Result;




}



}//big class


回复
jhwzqjh 2004-10-25
这不是编译原理里的内容呀
呵呵
回复
swzlxm 2004-10-25
小的时候,玩电脑学习机,不是有算二十四点的么,就是这方法,不过一时还写不出,最重要的就是分解.
回复
mqmmx 2004-10-25
我也不是很清楚不过看了一本vb.net技术内幕的书里写了有关正则表达式的例子可能对你有用。你可以把那本书找来一看。
回复
shuker 2004-10-25
算法我没有,不过复杂度应该和你算式可能出现的表达式有关
比如是否支持sin, cos,以及平方根号等
所以你最好要把这些定义清楚
回复
发帖
C#
创建于2007-09-28

10.5w+

社区成员

.NET技术 C#
申请成为版主
帖子事件
创建了帖子
2004-10-25 07:58
社区公告

让您成为最强悍的C#开发者