Java实现表达式求值

本文代码未使用栈

问题描述

输入一个表达式,表达式可以包括‘+’,‘-’,‘*’,‘/’,‘%’运算,可以出现整数小数,可以出现“()”,但要求输入格式合法

总体思路

当输入的表达式(下称s)中存在“()”时,对“()”内的表达式进行运算,并在s中将该“()”及其之中的表达式替换为运算结果;

直至s中无“()”,对s进行运算,输出结果。

运算思路

现在我们只需要考虑如何计算出一个没有“()”的表达式即可。

首先,明确:‘*’,‘/’,‘%’的运算优先级相同,且高于‘+’,‘-’,而‘+’,‘-’的运算优先级亦相同。

故我们可以将表达式运算拆为两部分,即乘除余的运算与加减的运算,现在,我们只需处理相同优先级的运算符,表达式的运算只需将二者按次序结合即可。(由于本算法思路为用结果替代指定的表达式部分,故二者不会相互干扰)

由于这两部分运算思路相仿,整体上的不同基本就是运算符的差异,故下面描述的算法适用于任一部分。

算法描述

1.确定运算符位置

检测表达式,记录首先出现的运算符。

2.确定运算数

以记录的运算符的位置分别向前向后检测,直到检测到运算符则停止,这两段字符串便是运算数(一个很重要的干扰项便是负数的存在,但由于要求输入的表达式必须合法,故在检测到‘-’的时候,只需检验下一个字符是不是运算符,若是或者没有下一个字符,则该运算数为负数,将该‘-’加入运算数的字段;若不是,则正常操作即可)。

3.确定运算数类型

检测两个运算数字段中是否有‘.’,若有,则设定结果为小数;否则,为整数。

4.检测与替换

检测表达式是否还含有该优先级的运算符,但要注意(没错,负数又来作妖了),若检测发现只有一个运算符,且那个运算符是‘-’并在第一个位置,这说明没有运算符了,那玩意(‘-’)是负数的东西,不用管。

在排除上述情况后,若有运算符,则继续对它进行运算;否则,用运算结果替换表达式(注意,若表达式在括号内部顺便把括号删了)。

代码

import java.util.Scanner;
public class java_fo {
	public static String multde(String in)
	//乘除余运算
	{
		int s1=in.indexOf('*');
		int s2=in.indexOf('/');
		int s3=in.indexOf('%');
		if(s1==-1&&s2==-1)
			s1=s3;
		else if(s1==-1&&s3==-1)
			s1=s2;
		else if(s2==-1&&s3==-1)
			;
		else
		{
			if(s1==-1)
				s1=in.length();
			if(s2==-1)
				s2=in.length();
			if(s3==-1)
				s3=in.length();
			s2=Math.min(s2, s3);
			s1=Math.min(s1, s2);
		}
		//确定运算符位置,若无运算符则为-1
		int t1=s1;
		while((in.charAt(t1-1)>='0'&&in.charAt(t1-1)<='9')||in.charAt(t1-1)=='.')
		{
			t1--;
			if(t1<1)
				break;
		}
		int t2=s1;
		if(t1==0);
		else if(t1==1)
			t1--;
		else if(in.charAt(t1-1)=='-')
			if(!(in.charAt(t1-2)>='0'&&in.charAt(t1-2)<='9'))
			t1--;
		if(!((in.charAt(t2+1)>='0'&&in.charAt(t2+1)<='9')||in.charAt(t2+1)=='.'))
			t2++;
		while((in.charAt(t2+1)>='0'&&in.charAt(t2+1)<='9')||in.charAt(t2+1)=='.')
		{
			t2++;
			if(t2>in.length()-2)
				break;
		}
		//获取运算数起/末位置
		String a1=in.substring(t1, s1);
		String a2=in.substring(s1+1, t2+1);
		int fla1,fla2;
		fla1=fla2=0;
		if(a1.indexOf('.')==-1)
		    fla1=1;
		if(a2.indexOf('.')==-1)
		    fla2=1;
		//检测两数是否为小数
		double m,n;
		int m1,n1;
		double m2,n2;
		if(fla1==0)
		{
			m=Double.parseDouble(a1);
			m2=m;
		}
		else
		{
			m1=Integer.valueOf(a1);
			m2=m1;
		}
		if(fla2==0)
		{
			n=Double.parseDouble(a2);
			n2=n;
		}
		else
		{
			n1=Integer.valueOf(a2);
			n2=n1;
		}
		//将两数转为对应的数字类型
		double res;
		if(in.charAt(s1)=='*')
			res=m2*n2;
		else if(in.charAt(s1)=='/')
			res=m2/n2;
		else
			res=m2%n2;
		//据运算符进行运算,得到结果
		String resu;
		if(fla1==1&&fla2==1)
			resu=String.valueOf((int)res);
		else
			resu=String.valueOf((float)res);
		//将结果转为对应类型,并转为字符串
		StringBuilder ini=new StringBuilder(in);
		ini.replace(t1,t2+1,resu);
		in=ini.toString();
		return in;
		//替换,返回替换后的表达式
	}
	public static String plusde(String in)
	//加减运算,思路与上同
	{
		int s1=in.indexOf('+');
		int s2=in.indexOf('-');
		if(s1==-1&&s2==-1)
			return in;
		else if(s1==-1&&s2==0)
			s1=in.lastIndexOf('-');
		else if(s1==-1)
			s1=s2;
		else if(s1!=-1&&s2==0)
			;
		else if(s1!=-1&&s2!=-1)
			s1=Math.min(s1, s2);
		int t1=s1;
		while((in.charAt(t1-1)>='0'&&in.charAt(t1-1)<='9')||in.charAt(t1-1)=='.')
		{
			t1--;
			if(t1<1)
				break;
		}
		int t2=s1;
		if(t1==0);
		else if(t1==1)
			t1--;
		else if(in.charAt(t1-1)=='-')
			if(!(in.charAt(t1-2)>='0'&&in.charAt(t1-2)<='9'))
			t1--;
		if(!((in.charAt(t2+1)>='0'&&in.charAt(t2+1)<='9')||in.charAt(t2+1)=='.'))
			t2++;
		while((in.charAt(t2+1)>='0'&&in.charAt(t2+1)<='9')||in.charAt(t2+1)=='.')
		{
			t2++;
			if(t2>in.length()-2)
				break;
		}
		String a1=in.substring(t1, s1);
		String a2=in.substring(s1+1, t2+1);
		int fla1,fla2;
		fla1=fla2=0;
		if(a1.indexOf('.')==-1)
		    fla1=1;
		if(a2.indexOf('.')==-1)
		    fla2=1;
		double m,n;
		int m1,n1;
		double m2,n2;
		if(fla1==0)
		{
			m=Double.parseDouble(a1);
			m2=m;
		}
		else
		{
			m1=Integer.valueOf(a1);
			m2=m1;
		}
		if(fla2==0)
		{
			n=Double.parseDouble(a2);
			n2=n;
		}
		else
		{
			n1=Integer.valueOf(a2);
			n2=n1;
		}
		double res;
		if(in.charAt(s1)=='+')
			res=m2+n2;
		else
			res=m2-n2;
		String resu;
		if(fla1==1&&fla2==1)
			resu=String.valueOf((int)res);
		else
			resu=String.valueOf((float)res);
		StringBuilder ini=new StringBuilder(in);
		ini.replace(t1,t2+1,resu);
		in=ini.toString();
		return in;
	}
	public static String work(String in)
	//统筹两种运算
	{
		while(in.indexOf('*')!=-1||in.indexOf('/')!=-1||in.indexOf('%')!=-1)
		    in=multde(in);
		//只要存在*,/,%便继续运算
		while(in.indexOf('+')!=-1||in.indexOf('-')!=-1)
		{
			if(in.indexOf('-')==0&&in.indexOf('-',1)==-1)
			if(in.indexOf('+')==-1)
				break;
				in=plusde(in);
		}
		//检测不是只剩一个负数,且有运算符,则继续运算
		return in;
	}
	public static void main(String[] arg)
	{
		Scanner in=new Scanner(System.in);
		String input=in.nextLine();
		input=input.replace(" ","");
		while(input.indexOf(')')!=-1)
		//检测是否有'('
		    {
			    int end=input.indexOf(')');
			    int sta=input.lastIndexOf('(',end);
			    String cir=input.substring(sta+1,end);
			    String cirt=input.substring(sta,end+1);
			    String cirr=work(cir);
			    input=input.replace(cirt,work(cir));
			    //替换,消括号
			}
		System.out.println(work(input));
	}
}

测试

输入:
(2+4/2*2-1)*2-6
输出:
4

输入:
5*11%3
输出:
1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章