java算法计算一元一次方程是昨年10月写的了,最近想写写算法就把它整理出来了。
核心思想是将方程转化为:aX+b = cX+d 的形式再进行计算,转化的思想是根据符号的优先级一层一层的分割。分割规则是先把+号能分割完的分割完,再把-号能分割完的分割完,最后分割*/号,不能从括号里面分割。具体过程如下:
方程:-3-12+2*(-7+5x)=-3-4+3*(6x+9)+10*3-20-30,以左边为例:
先根据 + 号 分割,结果为:
左:-3-12 + 右: 2*(-7+5x)
左边只能根据 - 号分割,右边根据*号分割
左:左:-3 - 右:12 + 右: 左:2 * 右:-7+5x
左边,右边都是 aX+b 形式直接计算,-3也是aX+b形式(a=0,b=-3)
左:-15 + 右:-14+10x
最后左侧将转化为:10x-29
完整代码如下:
/** * Created by LL on 2016/10/13. */ public class yiyuanyicifangcheng { public static void main(String[] args) { String string="-3-12+2*(-7+5x)=-3-4+3*(6x+9)+10*3-20-30"; double result = calculate(string); System.out.println("计算结果:x = "+result); } /** * 此类方法用于将字符串化为: aX+b 结构,结果返回a,b * @param str:需要计算的字符串 */ public static Result translate(String str) { str=deleteKH(str); char[] chars = str.toCharArray(); //先根据 + 号 将字符串分割完 for (int i = 0, kuHaoNum = 0; i < chars.length; i++) { kuHaoNum = getBracketsNum(kuHaoNum,i,chars); if(kuHaoNum==0&&("+".equals(chars[i]+""))){ //括号里面不分割 String s01=str.substring(0,i); String s02=str.substring(i+1, str.length()); Result result01=getResultFromString(s01); Result result02=getResultFromString(s02); Result result=new Result(); result.setA(result01.getA()+result02.getA()); result.setB(result01.getB()+result02.getB()); return result; } } //再根据 - 号 将字符串分割完 注意:- 号是从后往前分割 for (int i=chars.length-1,kuHaoNum=0;i>=0 ;i--) { kuHaoNum = getBracketsNum(kuHaoNum,i,chars); if(kuHaoNum==0&&("-".equals(chars[i]+""))){ //括号里面不分割 String s01=str.substring(0,i); String s02=str.substring(i+1, str.length()); Result result01=getResultFromString(s01); Result result02=getResultFromString(s02); Result result=new Result(); result.setA(result01.getA()-result02.getA()); result.setB(result01.getB()-result02.getB()); return result; } } //最后根据 *,/ 号 将字符串分割 for(int i=0,kuHaoNum=0;i<chars.length;i++){ kuHaoNum = getBracketsNum(kuHaoNum,i,chars); if(kuHaoNum==0&&("*".equals(chars[i]+"")||"/".equals(chars[i]+""))){ //括号里面不分割 String s01=str.substring(0, i); String fuhao=str.substring(i, i+1); String s02=str.substring(i+1, str.length()); Result result01=getResultFromString(s01); Result result02=getResultFromString(s02); Result result=new Result(); if(fuhao.equals("*")){ //因为是一元一次方程 不会出现 (aX+b)*(aX+b)的情况 if(result01.getA()!=0){ result.setA(result01.getA()*result02.getB()); result.setB(result01.getB()*result02.getB()); } if(result02.getA()!=0){ result.setA(result01.getB()*result02.getA()); result.setB(result01.getB()*result02.getB()); } if(result01.getA()==0&&result02.getA()==0){ result.setA(0.0); result.setB(result01.getB()*result02.getB()); } }else if(fuhao.equals("/")){ result.setA(result01.getA()/result02.getB()); result.setB(result01.getB()/result02.getB()); } return result; } } return null; } /** * 此类方法用于获取从起始位置到当前位置经历了几个括号 * @param num:括号数量 * @param index:字符数组的位置 * @param chars:字符数组 */ public static int getBracketsNum(int num,int index,char[] chars){ if("(".equals(chars[index]+"")){ num++; }else if(")".equals(chars[index]+"")){ num--; } return num; } /** * 此类方法用于将字符串转化为 aX+b 的形式 返回 Result * @param str:需要转化的字符串 */ public static Result getResultFromString(String str){ Result result = new Result(); if(str.equals("")){ result.setA(0.0); result.setB(0.0); }else if(isRightString(str)){ String standString=getStandardFormatString(str); standString=deleteKH(standString); result.setA(Double.parseDouble(standString.substring(0,standString.indexOf("x")))); result.setB(Double.parseDouble(standString.substring(standString.indexOf("x")+1,standString.length()))); }else if (isNum(str)){ result.setA(0.0); result.setB(Double.parseDouble(str)); }else{ result=translate(str); } return result; } /** * 此类方法用于计算方程 * @param string:需要计算的方程 */ public static double calculate(String string){ String string01=string.substring(0,string.indexOf("=")); String string02=string.substring(string.indexOf("=")+1,string.length()); Result result01=translate(string01); Result result02=translate(string02); System.out.println("原方程为:"+string); System.out.println("转化后的标准格式为:"+result01.getA()+"x+("+result01.getB()+")="+result02.getA()+"x+("+result02.getB()+")"); double a1=result01.getA(); double b1=result01.getB(); double a2=result02.getA(); double b2=result02.getB(); if(a1==a2&&b1!=b2){ System.out.println("此方程无解"); }else if(a1==a2&&a1==b2){ System.out.println("此方程有任意解"); }else if(a1!=a2){ return (b2-b1)/(a1-a2); } return 0.0; } /** * 此类方法用于判断字符串是否是数字 * @param str:需要判断的字符串 */ public static boolean isNum(String str){ boolean isNum = true; try{ double d = Double.parseDouble(str); }catch (Exception e){ isNum = false; } return isNum; } /** * 此类方法用于判断字符串是否是类似于 aX+b 格式 * @param s:需要判断的字符串 */ public static boolean isRightString(String s){ char[] c=s.toCharArray(); int j=0; for(int i=0;i<c.length;i++){ if("+".equals(c[i]+"")||"-".equals(c[i]+"")){ j++; } } if(s.contains("x")&&j<=1){ if(!s.contains("(")){ return true; }else if(s.contains("(")&&s.indexOf("(")==0){ return true; } } return false; } /** * 此类方法用于将字符串转化为 aX+b 标准格式 * @param s:需要转化的字符串 */ public static String getStandardFormatString(String s){ char[] c=s.toCharArray(); int t=0; StringBuffer s1=new StringBuffer(s); if(s.contains("+")||s.contains("-")){ for(int i=0;i<c.length;i++){ if("+".equals(c[i]+"")||"-".equals(c[i]+"")){ t=i;//t 用于记住 +,-号的位置 break; } } if(s.indexOf("x")<t){ return s; }else{ String s2=s.substring(0,t); String s3=s.substring(t,s.length()); StringBuffer ss=new StringBuffer(s3); ss.append(s2); return ss.toString(); } }else{ return s1.append("+0").toString(); } } /** * 此类方法用于去掉字符串最外层的括号 * @param str:需要处理的字符串 */ public static String deleteKH(String str){ if(str.startsWith("(")&&str.endsWith(")")){ str = str.substring(1, str.length() - 1); } return str; } /** * 此类定义了 aX+b 结构中的 a和b * 注意 这里的a,b可以为负,即aX-b也属于这种结构 */ public static class Result{ double a; double b;