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;
public Result(){
}
public Result(double a,double b) {
this.a=a;
this.b=b;
}
public double getA() {
return a;
}
public double getB() {
return b;
}
public void setA(double a) {
this.a = a;
}
public void setB(double b) {
this.b = b;
}
@Override
public String toString() {
return "Result{" +
"a=" + a +
", b=" + b +
'}';
}
}
}
运行结果: