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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章