c语言解一元一次方程(及一元高次方程)
首先,这里使用的方法是中缀表达式转后缀表达式,其次代码中紧展示了一元一次方程的解法过程,但是一元高次方程和该方法是同样的原理,
目录
第一部分:中缀转后缀
第二部分:方程的解法向中缀表达式的转换(本文重点)
第一部分:中缀转后缀表达式
中缀表达式转后缀表达式的逻辑参考下面链接:中缀转后缀,这里防止链接失效,再copy了一份
如下:
1.初始化两个栈:运算符栈s1和储存中间结果的栈s2;
2.从左至右扫描中缀表达式;
3.遇到操作数时,将其压s2;
4.遇到运算符时,比较其与s1栈顶运算符的优先级:
(1)如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(2)否则,若优先级比栈顶运算符的高,也将运算符压入s1;
(3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较;
5.遇到括号时:
(1)如果是左括号"(",则直接压入s1
(2)如果是右括号")",则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃6.重复步骤2至5,直到表达式的最右边
7.将s1中剩余的运算符依次弹出并压入s2
8.依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
案例分析:
将中缀表达式 “1+((2+3)*4)-5” 转换为后缀表达式的过程如下:
下面是我写的c代码
注意:我写的代码中并没有对负号和减号进行区分,只能识别减号,出现负号的话将会出错,可以在负号前加个0解决这个问题;并且表达式中只能出现整数,不可以出现小数
double ToSuffixExpression(char* buf) //buf指需要传进去的字符串表达式
{
double number[50]; //数字栈
char op[50] = {'\0'}; //运算符栈
int m = 0, n = 0; //m是number的栈顶,n是运算符栈顶
int i = 0;
while(buf[i] != '\0')
{
if(isdigit(buf[i])) //遇到数字的处理方式
{
int temp = buf[i] - '0';
while(isdigit(buf[i+1]))
{
temp *= 10;
temp += buf[++i] - '0';
}
number[m++] = (double)temp;
}
else if(buf[i] == '+' || buf[i] == '-' || buf[i] == '*' || buf[i] == '/') //是操作符的处理方式
{
if(n == 0 || op[n-1] == '(') //步骤4.1的处理
op[n++] = buf[i];
else if((buf[i] == '*' || buf[i] == '/') && (op[n-1] == '+' || op[n-1] == '-')) //步骤4.2的处理
op[n++] = buf[i];
else //步骤4.3的处理
{ //这里不将操作符推入数字栈,而是直接将局部结果计算出来
if(op[n-1] == '+')
number[m-2] += number[m-1];
else if(op[n-1] == '-')
number[m-2] -= number[m-1];
else if(op[n-1] == '*')
number[m-2] *= number[m-1];
else
number[m-2] /= number[m-1];
op[--n] = '\0';
--m;
continue;
}
}
else if(buf[i] == '(' || buf[i] == ')') //是'('和')'的处理方式
{
if(buf[i] == '(') //步骤5.1的处理
op[n++] = '(';
else //步骤5.2的处理
{ //这里不将操作符推入数字栈,而是直接将局部结果计算出来
while(op[n-1] != '(')
{
if(op[n-1] == '+')
number[m-2] += number[m-1];
else if(op[n-1] == '-')
number[m-2] -= number[m-1];
else if(op[n-1] == '*')
number[m-2] *= number[m-1];
else
number[m-2] /= number[m-1];
op[--n] = '\0';
--m;
}
op[--n] = '\0';
}
}
++i;
}
while(n > 0)
{ //这里不将操作符推入数字栈,而是直接将局部结果计算出来
if(op[n-1] == '+')
number[m-2] += number[m-1];
else if(op[n-1] == '-')
number[m-2] -= number[m-1];
else if(op[n-1] == '*')
number[m-2] *= number[m-1];
else
number[m-2] /= number[m-1];
--m;
--n;
}
return number[0]; //正确运行的话number栈肯定只有一个数字
}
第二部分:方程向中缀表达式的转换
步骤一:将方程等号右侧全部移到等号左侧,变成等号右侧为0的形式。这一步很简单。
步骤二:如果能把方程化简成ax+b=0的形式问题就解决了,将步骤一的等号左侧表达式所有变量赋值成0,变成一个新的中缀表达式,经过ToSuffixExpression()计算的结果就是b。同样的方法,再将所有的变量赋值成1计算一次,计算结果记作sum,那么a = sum - b,问题解决。
#include <stdio.h>
#include <ctype.h>
double ToSuffixExpression(char* buf);
int main()
{
char var;
char buf[100] = {'\0'}, buf1[100] = {'\0'}, buf2[100] = {'\0'};
//buf1是将变量赋值成1的字符串,buf2是将变量赋值成0的字符串
gets(buf);
/*去除表达式的空格*/
// int p = 0, q = 0;
// while(buf[p] != '\0')
// {
// while(buf[p] == ' ') ++p;
// buf[q++] = buf[p++];
// }
// buf[q] = '\0';
/*上述注释代码是去掉表达式中的空格,如果表达式有空格,就不可以注释*/
int i = 0, loc1 = 0, loc2 = 0;
if(buf[0] == '-')
{
buf1[loc1++] = '0';
buf2[loc2++] = '0';
}
while(buf[i] != '\0')
{
if(isalpha(buf[i]))
{
var = buf[i]; //var字符记录变量名
if(i == 0 || (i > 0 && !isdigit(buf[i-1]))) //处理当前位置是字母(未知数),但是前一个字符不是数字,也即自变量的系数是1省略的情况
{
buf1[loc1++] = '1'; //直接将该变量换成1
buf2[loc2++] = '0'; //直接将该变量换成0
}
else //自变量的系数不是1的情况
{
buf1[loc1++] = '*';
buf1[loc1++] = '1';
buf2[loc2++] = '*';
buf2[loc2++] = '0';
}
}
else if(buf[i] == '=') //当前位置是'='的情况
{
buf1[loc1++] = '-';
buf1[loc1++] = '(';
buf2[loc2++] = '-';
buf2[loc2++] = '(';
if(buf[i+1] == '-' || buf[i+1] == '+') //如果等号后第一个符号是负号'-'或正号'+',在其前加一个0
{
buf1[loc1++] = '0';
buf2[loc2++] = '0';
}
}
else if(buf[i] == '(' && (buf[i+1] == '-' || buf[i+1] == '+')) //如果出现"(-"或者"(+",在中间加个'0'
{
buf1[loc1++] = '(';
buf2[loc2++] = '(';
buf1[loc1++] = '0';
buf2[loc2++] = '0';
}
else
{
buf1[loc1++] = buf[i];
buf2[loc2++] = buf[i];
}
++i;
}
buf1[loc1] = ')'; //末尾加')'
buf2[loc2] = ')';
//printf("%s\n", buf1); //打印变量变成1的表达式
//printf("%s\n", buf2); //打印变量变成0的表达式
double sum = ToSuffixExpression(buf1);
double b = ToSuffixExpression(buf2);
double a = sum - b;
printf("%c=%.3f\n",var, (-b/a));
return 0;
}
举个例子,运行结果如下:
通过一元一次方程的解法,可以拓展一下,高次方程也可以进行赋值0或1来计算各项系数。
通过上述赋值方式,可以计算a = sum1 - c,b = sum2 - c,然后使用二次函数的求根公式即可。