首页 > 试题广场 >

二次方程计算器

[编程题]二次方程计算器
  • 热度指数:6216 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
设计一个二次方程计算器

输入描述:
每个案例是关于x的一个二次方程表达式,为了简单,每个系数都是整数形式。


输出描述:
每个案例输出两个实数(由小到大输出,中间由空格隔开),保留两位小数;如果无解,则输出“No Solution”。
示例1

输入

x^2+x=3x+4

输出

-1.24 3.24

提供两种方法:
第一种方法:只适用本题的情况,第二种则通用

package com.speical.first;
import java.text.DecimalFormat;
import java.util.Scanner;
/** 
* 二元一次方程组解法
* 
* 
* @author special
* @date 2018年1月2日 下午3:24:01
*/
public class Pro90 {
    static DecimalFormat df = new DecimalFormat("0.00");
    /**
     * 解析从fromIndex 到 toIndex(不包括)的数
     * 如果num = 0 且 toIndex不是末尾,那么说明该数
     * 是未知数的系数且为1(因为1会省略不写)
     * [@param fromIndex
     * @param toIndex
     * @param expression
     * @return](/profile/547241) */
    public static int parseInt(int fromIndex, int toIndex, String expression){
        int num = 0;
        boolean flag = true;    //记录正负
        if(expression.charAt(fromIndex) == '-'){
            flag = false;
            fromIndex++;
        }else if(expression.charAt(fromIndex) == '+'){
            flag = true;
            fromIndex++;
        }
        while(fromIndex < toIndex){
            num = num * 10 + (expression.charAt(fromIndex) - '0');
            fromIndex++;
        }
        if(num == 0 && toIndex < expression.length()) num = 1; //如果是0且是未知数的系数,那么为1
        return flag ? num : -num;
    }
    /**
     * 知道了3个系数,那么很容易求答案了
     * 注意该题的答案保留2位小数不用四舍五入
     * 该死的,format会自动四舍五入
     * 你若是不想四舍五入,必须借助DecimalFormat类
     * @param a
     * @param b
     * @param c
     */
    public static void caculate(int a, int b, int c){
        double temp = b * b - 4 * a * c;
        if(temp < 0){
            System.out.println("No Solution");
        }else{
            temp = Math.sqrt(temp);
            double result1 = ((-b) + temp) / (2 * a);
            double result2 = ((-b) - temp) / (2 * a);
            if(result1 > result2){
                double max = result1;
                result1 = result2;
                result2 = max;
            }
            System.out.println(df.format(result1) + " " + df.format(result2));
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        while(input.hasNext()){
            /**
             * 这个表达式有个特点
             * 就是一次项等号左边和右边都会出现
             * 一次项若左边没有,代表这个方程没有一次项了
             * 常数项只出现等号右边
             */
            String expression = input.nextLine();
            int fromIndex = 0, toIndex;  //2次项的系数开头索引为0
            toIndex = expression.indexOf('x');  //结尾索引为第一次出现x的位置
            int a = parseInt(fromIndex, toIndex,expression); //解析出a
            fromIndex = expression.indexOf('^') + 2; //一次项的系数开始位置
            toIndex = expression.indexOf('x',fromIndex); //一次项的系数结束的位置
            int b = 0, c = 0;
            if(toIndex != -1){ //注意可能这个二元方程等号左边没有一次项,所以要判断一下
                b = parseInt(fromIndex, toIndex, expression); //如果有一次项,解析出来,这里指的是等号左边的
                fromIndex = expression.indexOf('=') + 1; //等号右边一次项开始的位置
                toIndex = expression.indexOf('x', fromIndex); //等号右边一次项结束的位置
                if(toIndex != -1){  //注意可能这个二元方程等号右边没有一次项,所以要判断一下
                    b -= parseInt(fromIndex, toIndex, expression); //如果等号右边有一次项,解析出来,并减去它
                    fromIndex = toIndex + 1; //指向常数项开始的位置
                }
            }else{
                fromIndex = expression.indexOf('=') + 1; //若果没有一次项,那么直接找出等号右边的常数项开始的位置
            }
            toIndex = expression.length(); //常数项结尾的位置,也就是表达式末尾
            c = -parseInt(fromIndex, toIndex, expression); // -c
            caculate(a,b,c); //计算即可
        }
    }
}

第二种

package com.speical.improve;

import java.text.DecimalFormat;
import java.util.Scanner;

/** 
* 二元一次方程
* 
* 分别对等号两边的字符串进行解析,求出各系数
* @author special
* @date 2018年1月2日 下午5:30:22
*/
public class Pro90Improve1 {
    static DecimalFormat df = new DecimalFormat("0.00");
    static int[] nums = new int[3];
    private static boolean isNum(char ch){
        return ch >= '0' && ch <= '9';
    }
    public static void getNum(int fromIndex, int toIndex, String expression, boolean flag){
        int num = 0;
        char ch;
        boolean positive = true;
        int[] temp = new int[3];
        for(int i = fromIndex; i < toIndex; i++){
            ch = expression.charAt(i);
            if(isNum(ch)){
                while(i < toIndex && isNum(expression.charAt(i))){
                    num = num * 10 + expression.charAt(i) - '0';
                    i++;
                }
                if(i < toIndex && expression.charAt(i) != 'x' || i == toIndex){
                    temp[2] = positive ? num : -num;
                    num = 0;
                    positive = true;
                }
                i--; //记得减一,因为循环体的最后也有i++
            }else if(ch == 'x'){
                if(num == 0){
                    num = 1;
                }
                if(i < toIndex - 1 && expression.charAt(i + 1) == '^'){
                    temp[0] = positive ? num : -num;
                    i += 2;
                }else {
                    temp[1] = positive ? num : -num; 
                }
                num = 0;
                positive = true;
            }
            else if(ch == '-'){
                positive = false;
            }
        }
        for(int i = 0; i < 3; i++){
            nums[i] = flag ? temp[i] : nums[i] - temp[i];
        }

    }
    /**
     * 知道了3个系数,那么很容易求答案了
     * 注意该题的答案保留2位小数不用四舍五入
     * 该死的,format会自动四舍五入
     * 你若是不想四舍五入,必须借助DecimalFormat类
     * @param a
     * @param b
     * @param c
     */
    public static void caculate(int a, int b, int c){
        double temp = b * b - 4 * a * c;
        if(temp < 0){
            System.out.println("No Solution");
        }else{
            temp = Math.sqrt(temp);
            double result1 = ((-b) + temp) / (2 * a);
            double result2 = ((-b) - temp) / (2 * a);
            if(result1 > result2){
                double max = result1;
                result1 = result2;
                result2 = max;
            }
            System.out.println(df.format(result1) + " " + df.format(result2));
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        while(input.hasNext()){
            String expression = input.nextLine();
            int index = expression.indexOf('=');
            getNum(0, index, expression, true); //等号左边处理
            getNum(index + 1, expression.length(), expression, false); //等号右边处理
            caculate(nums[0],nums[1],nums[2]); //计算即可
        }
    }
}
编辑于 2018-01-02 19:45:24 回复(0)
思路是以'+','=','-'为界,把方程分成每一项,比如"x^2+x=3x+4"分成"x^2","x","3x","4",若子串有x且有^是二次项,二次项系数加(前面是'+')或减(前面是'-')对应的值(若省略则是1,比如x^2省略前面的常数系数1),子串有x无^是一次项,无x且不空是常数项。另外越过'='相当于变号,把系数全取相反数。没通过是因为这个用例,0确实是一个根,你这-0什么意思?代码(c++11):
#include<string>
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int main() {
    int a, b, c, d, p, q, i, len;//系数abc,判别d
    string eqt, sub; // eqt is equation, sub is substring.
    while (cin>> eqt) {
        a = b = c = p = 0;
        len = eqt.length();
        for (i=0; i<len+1; ++i)
            if (i==len || eqt[i]=='+' || eqt[i]=='=' || eqt[i]=='-') {
                sub = eqt.substr(p, i-p);//获得子串并分析
                if ((q=sub.find('x')) != string::npos) {//有x是一次或二次项
                    if (sub.find('^') != string::npos)//有^是二次项,处理a
                        a += (eqt[p-1]=='-'?-1:1)*(q?stoi(sub.substr(0, q)):1);
                    else b += (eqt[p-1]=='-'?-1:1)*(q?stoi(sub.substr(0, q)):1);
                } else if (sub != "")//没x且不是空则是常数项
                        c += (eqt[p-1]=='-'?-1:1)*stoi(sub);
                if (eqt[i] == '=') { //跨过等号相当于移项,要变号 
                    a = -a; b = -b; c = -c;
                }
                p = i+1;
            }
        if (a < 0) { //为保证更小的根先输出,全部变号使a为正且不影响正解
            a = -a; b = -b; c = -c;
        }
        d = b*b-4*a*c; //根的判别式
        if (d < 0)
            printf("No Solution\n");
        else printf("%.2f %.2f\n", (-sqrt(double(d))-double(b))/(2*double(a)),
                        (sqrt(double(d))-double(b))/(2*double(a)));
    }
    return 0;
}

发表于 2018-02-17 13:22:20 回复(14)
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <ctype.h>
#include <vector>
#include <cmath>

using namespace std;

int a = 0, b = 0, c = 0;

void get_coe(string str) {
    int len = str.length();
    // 为了最后时[i+1]操作不会报错 
    str.append(1, '+');
    int t = 0;
    int isNegative = 1;    // 是否为负数 
    int afterEqual = 1;    // 是否在等号右边 
    for(int i = 0; i < len; i++) {
        
        if(str[i] == '=') {
            afterEqual = -1;
        }
        
        if(isdigit(str[i])) {
            t = t*10 + (str[i]-'0');
        } else if(str[i] == '-') {
            isNegative = -1;
        } else if(str[i] == '^') { 
            i++;
        } else {
            if(str[i] == 'x' && str[i+1] == '^') {
                if(t == 0)  t = 1;
                a += t*isNegative*afterEqual;
            } else if(str[i] == 'x') {
                if(t == 0)  t = 1;
                b += t*isNegative*afterEqual;
            } else {
                c += t*isNegative*afterEqual;
            }
            t = 0;
            isNegative = 1;
        }
        
        if(i == len-1 && isdigit(str[i])) {
            c += t*isNegative*afterEqual;
            break;
        }
    }
}

int main()
{
    string str;
    while(cin>>str) {
        get_coe(str);
        int d = b*b-4*a*c;
        if(d < 0) {
            cout<<"No Solution"<<endl; 
        } else {
            double t = sqrt(d);
            double x1 = (-1*b - t)/(2*a);
            double x2 = (-1*b + t)/(2*a);
            printf("%.2lf %.2lf\n", min(x1, x2), max(x1, x2));
        }
        
        a = 0; b = 0; c = 0;
    }
    return 0;
}

发表于 2018-03-20 19:28:56 回复(0)
思路:逐个解析字符串分析出系数,用到一点小技巧,利用堆栈存储数据和操作符,利用getch和ungetch来实现流式操作。
/* quadratic equation computation
 * eg: input: x^2+x=3x+4
 *     output: -1.24 3.24
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stack>
#include <algorithm>

using namespace std;

#define NUMBER    '0'
#define MAXOP    (100)
char str[MAXOP];
int pos = 0;

int getch()
{
    if (pos < strlen(str))
        return str[pos++];
    return EOF;
}

void ungetch()
{
    pos--;
}

int getop(char s[])
{
    int c, i = 0;

    s[0] = c = getch();
    s[1] = '\0';

    if (!isdigit(c))
        return c;

    while (isdigit(s[++i] = c = getch()))
        ;
    s[i] = '\0';

    if (c != EOF)
        ungetch();

    return NUMBER;
}

int main()
{
    while (scanf("%s", str) != EOF) {  
        char s[10]; /* max coefficient bits is 10 */
        int type, a=0, b=0, c=0, left=1;
        stack<char> opr;
        stack<int>  opd;

        pos = 0;
        while ((type = getop(s)) != EOF) {
            switch(type) {
            case NUMBER:
                int t; char ch;
                t = left * atoi(s);
                if (!opr.empty() && (ch = opr.top()) == '-') {
                    t = -t;
                    opr.pop();
                }
                opd.push(t);
                break;
            case '+': case '-': 
                opr.push(type);
                break;
            case '=':
                left = -1;
                break;
            case '^':
                if (opd.empty()) {
                    a += 1;
                } else {
                    a += opd.top();
                    opd.pop();
                }
                getch(); /*eat following '2'*/
                break;
            case 'x':
                if (getch() != '^') {
                    if (opd.empty()) {
                        b += 1;
                    } else {
                        b += opd.top();
                        opd.pop();
                    }
                }
                ungetch();
                break;
            }
        }

        if (!opd.empty()) {
            c = opd.top();
            opd.pop();
        }

        double delta, x1, x2;
        delta = pow(b, 2) - 4*a*c;

        if (delta >= 0) {
            delta = sqrt(delta);
            x1 = (-b-delta) / (2*a);
            x2 = (-b+delta) / (2*a);
            if (x1 > x2)
                swap(x1, x2);
            printf("%.2lf %.2lf\n", x1, x2);
        } else {
            printf("No Solution\n");
        }
    }

    return 0;
}


发表于 2019-02-14 14:46:39 回复(0)
def getNum(equation,digit):        #得到该次幂前面的系数
    index = equation.find(digit)
    if index >= 0:
        temp = '#'                #用一个非数字符代替特殊的1被隐藏
        index -= 1
        while index >= 0 and(equation[index].isdigit() or equation[index] == '-'):
            temp = equation[index] + temp
            index -= 1
        if temp == '#':
            return 1
        elif temp == '-#':
            return -1
        else:
            return int(temp[:-1])
    return 0

while True:
    try:
        equation = input().split('=')
        a = getNum(equation[0],'x^2')-getNum(equation[1],'x^2')
        for i in range(2):
            if equation[i].find('x^2') != -1:
                equation[i] = equation[i][equation[i].find('x^2')+3:]
        b = getNum(equation[0],'x')-getNum(equation[1],'x')
        for i in range(2):
            if equation[i].find('x') != -1:
                equation[i] = equation[i][equation[i].find('x')+1:]
        c = 0                     #只要得到方程ax^2+bx+c=0中的a,b,c,之后就很好算
        if equation[0]:
            c = int(equation[0])
        if equation[1]:
            c -= int(equation[1])
        if b*b-4*a*c < 0:
            print('No Solution')
        else:
            x1 = (-b+(b*b-4*a*c)**0.5)/(2*a)
            x2 = (-b-(b*b-4*a*c)**0.5)/(2*a)
            if x1 > x2:
                x1,x2 = x2,x1
            print('%.2f %.2f'%(x1,x2))
    except Exception:
        break
编辑于 2018-10-14 14:10:53 回复(0)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<stack>
#include<cmath>
using namespace std;
int cba[3],epos;
char str[100];

void Read(int &co,int &eo,int &i){
    if(str[i]==0) {eo=-1; return ;}
    int flag=0;
    if(str[i]=='=') {++i;}
     if(str[i]=='-') {++i;++flag;}
    if(str[i]=='+') ++i;
    if(i>epos) ++flag;
    if(str[i]=='x'){
        co=1;
        if(str[i+1]=='^'){i+=2; eo=str[i]-'0'; ++i;}
        else {i++; eo=1;}
    }
    else{
        co=0;
        while(str[i]>='0'&&str[i]<='9') 
            {co=co*10+str[i]-'0'; ++i;}
        if(str[i]=='x'){ 
            if(str[i+1]=='^'){i+=2; eo=str[i]-'0';++i;}
            else {i++; eo=1;} 
        }
        else {eo=0;++i;}
    }
    if(flag%2){
            co=0-co;
    }
}
int main(){
    while(scanf("%s",str)==1){
        for(int i=0;;++i){
            if(str[i]==0)break;
            if(str[i]=='=') {epos=i; break;}
        }
        int co,eo,i=0;
        memset(cba,0,sizeof(cba));
        while(1){
            Read(co,eo,i);
            if(eo==-1) break;
            cba[eo]+=co;
        }
        int a=cba[2],b=cba[1],c=cba[0];
       // printf("a:%d,b:%d,c:%d\n",a,b,c);
        double delta=b*b-4*a*c;
        if(delta<0) printf("No Solution\n");
        else {
            double x1,x2;
            x1=(0-b-sqrt(delta))/(2*a);
            x2=(0-b+sqrt(delta))/(2*a);
            if(x1>x2) swap(x1,x2);
            printf("%.2f %.2f\n",x1,x2);
        }
    }
    return 0;
}


发表于 2018-05-06 19:06:36 回复(0)
//我觉得我的代码可以往上爬一爬
#include<stdio.h>
#include<math.h>
#include<string.h> 
#include<algorithm>
using namespace std;
int main(){    
    char str[100];
    int eqPos;// =位置 
    while(scanf("%s",str)!=EOF){
        int a=0,b=0,c=0;        //a为二次项系数,b为一次项系数,c为常数
        for(int i=0;i<strlen(str);i++){       //找到等号的位置,后面比较用
            if(str[i]=='='){
                eqPos=i;
            }
        }
        for(int i=0;i<strlen(str);i++){     //一次遍历即可
            if(str[i]=='x'){  //不是常数项
                if(str[i+1]=='^'){    //是二次的,则求其系数
                    if(i==0)a=a+1;  //在开头的x^2,系数为1
                    else{
                        int t=0,k=1;
                        int site=i-1;
                        while(site>=0&&str[site]>='0'&&str[site]<='9'){ //往前倒,算系数
                            t=(str[site]-'0')*k+t;
                            k*=10;
                            site--;
                        }
                        if(site==i-1)t=1;//qianm单独的x^2,系数为1 
                        if(i>eqPos){
                            if(str[site]!='-')a-=t;
                            else a+=t;
                        }
                        else{
                            if(str[site]!='-')a+=t;
                            else a-=t;
                        }
                    }
                    i+=2;//  x^2  后移两位继续识别
                }else{    //一次项x
                    if(i==0)b=b+1;//x在开头,系数为1
                    else{
                        int t=0,k=1;
                        int site=i-1;
                        while(site>=0&&str[site]>='0'&&str[site]<='9'){//往前倒,求出系数
                            t=(str[site]-'0')*k+t;
                            k*=10;
                            site--;
                        }
                        if(site==i-1)t=1;//单独的x 系数为1 
                        if(i>eqPos){//等号右边
                            if(str[site]!='-')b-=t;//符号为+
                            else b+=t;
                        }
                        else{//等号左边
                            if(str[site]!='-')b+=t;//符号为+
                            else b-=t;
                        }
                    }
                }
            }else if(str[i]>='0'&&str[i]<='9'){   //暂且认为是常数项               
                    int site=i;
                    int t=0;
                    while(site<strlen(str)&&str[site]>='0'&&str[site]<='9'){//不管是不是常数,先把数算出来备用
                        t=str[site]-'0'+t*10;
                        site++;
                    }                 
                    if(str[site]!='x'){   //如果遇到x,就不是常数了
                        if(i>eqPos){
                            if(str[i-1]!='-')c-=t;
                            else c+=t;
                        }
                        else{
                            if(str[i-1]!='-')c+=t;
                            else c-=t;
                        }
                        i=site;
                    }   
            }else{}
        }
        //printf("a=%d,b=%d,c=%d\n",a,b,c);
        double ans1,ans2;
        if(b*b-4*a*c>=0){
            ans1=(double)(-b-sqrt(b*b-4*a*c))/(2*a);
            ans2=(double)(-b+sqrt(b*b-4*a*c))/(2*a);
            if(ans1>ans2){   //小的在前
                swap(ans1,ans2);
            }
            printf("%.2f %.2f\n",ans1,ans2);
        }else{
            printf("No Solution\n");
        }
    }
    
    return 0;
}
发表于 2019-03-23 16:57:40 回复(0)
可以用状态机来做
#include <stdio.h>
#include <math.h>

#define WAIT 0
#define MEET_NUM 1
#define MEET_X 2


int is_num(char c){
    int tmp=(int)c;
    return (tmp >=(int)'0' && tmp<=(int)'9');
}

int main(){
    char tmp;
    int side=1;
    int a=0,b=0,c=0;
    int state=WAIT;
    int current_num=0;
    int sign=1;
    while(scanf("%c",&tmp)!=EOF){
        if(tmp=='-'){
            sign=-1;
         }
        if(tmp=='=') side=-1;
        switch(state){
            case WAIT:if(tmp=='x'){
                state=MEET_X;
                current_num=sign*side;
                break;
            }
                if(is_num(tmp)){
                    current_num=((int)tmp-(int)'0')*sign*side;
                    state=MEET_NUM;
                    break;
                }
                break;
            case MEET_NUM:if(tmp=='x'){
                state=MEET_X;
                break;
            }
                else{
                    if(is_num(tmp)){
                        int t=(int)tmp-(int)'0';
                        current_num=current_num*10+t*side*sign;
                        break;
                    }
                else{
                    c+=current_num;
                    sign=1;
                    state=WAIT;
                    break;
                }
                }
            case MEET_X:if(tmp=='^'){
                a+=current_num;
                sign=1;
                scanf("%c",&tmp);
                state=WAIT;
                break;
            }
            else{
                b+=current_num;
                sign=1;
                state=WAIT;
                break;
            }
        }
    }
    if(state==MEET_X) b+=current_num;
    if(state==MEET_NUM) c+=current_num;
    float b2_4ac=(float)(b*b-4*a*c);
    if(b2_4ac<0){
        printf("No Solution\n");
    }
    else{
        float result1=((float)b*(-1.0)-fabs((sqrt(b2_4ac))))/(2*a);
        float result2=((float)b*(-1.0)+fabs((sqrt(b2_4ac))))/(2*a);
        if(result2<result1){
            float temp=result2;
            result2=result1;
            result1=temp;
        }
        printf("%.2f %.2f\n",result1,result2);
    }
}

发表于 2018-08-28 13:51:14 回复(0)
# 正则表达式解法
import re
import math
from itertools import chain

def get_coef(regex, lexp, rexp):
    coef = 0
    pos = re.finditer(regex, lexp)
    neg = re.finditer(regex, rexp)
    for match in chain(pos, neg):
        num = match.group(1)
        num = 1 if len(num) == 0 else int(num)
        coef = coef + num if "=" in match.string else coef - num
    return coef

if __name__ == '__main__':
    lexp, rexp = input().split("=")
    lexp += "="

    coef2 = get_coef(r"((?:\+|-|)\d+|)x\^2", lexp, rexp);
    coef1 = get_coef(r"((?:\+|-|)\d+|)x(?!\^2)", lexp, rexp);
    coef0 = get_coef(r"(?<![\d^])((?:\+|-|)\d+)(?![\dx])", lexp, rexp);

    # print("%d %d %d" %(coef2, coef1, coef0))

    try:
        delta = math.sqrt(coef1**2 - 4 * coef2 * coef0)
    except:
        print("No Solution")
        exit(0)

    rt1 = (-coef1 - delta) / (2 * coef2)
    rt2 = (-coef1 + delta) / (2 * coef2)

    if rt1 > rt2:
        rt1, rt2 = rt2, rt1

    print("%.2f %.2f" % (rt1, rt2))

编辑于 2018-07-01 11:05:03 回复(0)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int getNum(char* s,int *m,int i){

    int c=0,num=0;

    while(s[i]>='0'&&s[i]<='9'){

        num=num*10+s[i]-'0';

        ++i;

        ++c;

    }

    *m=c;

    return num;

}

double root(int p){

    double root=1.0;

    while(root*root-p>=1e-9||root*root-p<=-1e-9)

        root=(root+p/root)/2;

    return root;

}

void solution(int a,int b,int c){

    int p=b*b-4*a*c;

    double s1,s2,ro=0.0;

    if(p<0)

        printf("No Solution\n");

    else{

        ro=root(p);

        a*=2;

        b=-b;

        s1=(b+ro)/a;

        s2=(b-ro)/a;

        printf("%.2f %.2f\n",s2,s1);

    }

}

int main(){

    char f[100];

    scanf("%s",f);

    int temp=1,*mov,i=0, a=0,b=0,c=0,flag=1,sig=1;

    while(f[i]){

        temp=0;

        if(f[i]>='0'&&f[i]<='9'){

            temp=getNum(f,mov,i)*flag*sig;//record the parameter

            i+=*mov;

            if(f[i]!='x')

                c+=temp;

            else if(f[i+1]=='^'&&f[i+2]=='2'){

                a+=temp;

                i+=3;

            }

            else{

                b+=temp;

                ++i;

            }

        }

        else if(f[i]=='+'||f[i]=='-'||f[i]=='='){

            switch (f[i]) {

                case '+':

                    ++i;

                    sig=1;

                    break;

                case '-':

                    sig=-1;

                    ++i;

                    break;

                case '=':

                    flag=-1;

                    sig=1;

                    ++i;

                    break;

            }

        }

        else if(f[i]=='x'){

                if(f[i+1]=='^'&&f[i+2]=='2'){

                    a+=sig*flag;

                    i+=3;

                }

                else{

                    b+=sig*flag;

                    i+=1;

                }

            }

        }

    solution(a, b, c);

}
//为什么不对啊,,,我自己的机器上可以的,。提示信息:运行错误:请检查是否存在数组、列表等越界非法访问,内存非法访问等情况

发表于 2017-01-11 23:55:53 回复(0)
虽然被该题的标签给难住了(说是二分,但实际上利用求根公式就可以了。因此,该题的难点在于如何处理将给定的字符串的相关系数提取出来。
发表于 2022-02-12 15:35:43 回复(0)
parse部分代码:
int co[3];

int getLevel(string& t, int& p) {
    if (p + 1 >= t.length() || t[p + 1] != '^') {
        return 1;
    } else {
        p += 2;
        return t[p] - '0';
    }
}

void parse(string& t) {
    co[0] = co[1] = co[2] = 0;
    int right = 1;
    int nagtive = 1;
    int now = 0;
    for (int i = 0; i < t.length(); i++) {
        if (isdigit(t[i]))
            now = now * 10 + t[i] - '0';
        else {
            if (t[i] == 'x') {
                if (now == 0) now = 1;
                co[getLevel(t, i)] += right * nagtive * now;
                nagtive = 1;
                now = 0;
            } else {
                if (now != 0) {
                    co[0] += right * nagtive * now;
                    nagtive = 1;
                    now = 0;
                }
                if (t[i] == '-')
                    nagtive = -1;
                else if (t[i] == '=')
                    right = -1;
            }
        }
    }
    if (now != 0)
        co[0] += right * nagtive * now;
}


编辑于 2024-03-22 18:28:39 回复(0)
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;

struct Polynomial { //(一元)二次多项式
    int a, b, c;    //系数(a:二次项系数,b:一次项系数,c:常数项)
    Polynomial(string str) {    //构造函数
        int position = str.find("x^2");
        if (position != -1) {   //无二次项
            a = atoi(str.substr(0, position).c_str());
            str = str.substr(position + 3);
            if (str[0] == '+') {        //一次项系数为正
                str = str.substr(1);    //吃掉加号
            }
        }
        position = str.find("x");
        if (position != -1) {   //无一次项
            b = atoi(str.substr(0, position).c_str());
            str = str.substr(position + 1);
            if (str[0] == '+') {        //常数项为正
                str = str.substr(1);    //吃掉加号
            }
        }
        c = atoi(str.c_str());
    }
};

struct Equation {       //(一元)二次方程
    Polynomial* left;   //方程左式
    Polynomial* right;  //方程右式
    Equation(string str) {  //构造函数
        int position = str.find("=");
        left = new Polynomial(str.substr(0, position));
        right = new Polynomial(str.substr(position + 1));
    }
    void solve() {  //方程求解
        int a = left->a - right->a;
        int b = left->b - right->b;
        int c = left->c - right->c;
        int delta = b * b - 4 * a * c;
        if (delta < 0) {
            cout << "No Solution" << endl;
        } else {
            double x1 = (-b * 1.0 - sqrt(delta)) / 2 * a;
            double x2 = (-b * 1.0 + sqrt(delta)) / 2 * a;
            cout << setiosflags(ios_base::fixed) << setprecision(2) << x1 << " "
                 << setiosflags(ios_base::fixed) << setprecision(2) << x2 << endl;
        }
    }
};

int main() {
    string str;
    while (cin >> str) {
        Equation(str).solve();
    }
    return 0;
}

编辑于 2024-03-01 15:22:56 回复(0)
#include <bits/stdc++.h>
using namespace std;
void js(string s1, int& xs1, int& xs2, int& cs) {
    s1 = '+' + s1 + "+0+";
    for (int i = 0; i < s1.size(); i++)
        if (s1[i] == 'x' && s1[i + 1] != '^') {
            if (i == 0 || s1[i - 1] == '+') xs2++;
            if (i > 0 && s1[i - 1] == '-') xs2--;
            if (i > 0) {
                int j = i - 1;
                int u = 0, k = 1;
                while (j >= 0 && s1[j] >= '0' && s1[j] <= '9') {
                    u = u + (s1[j] - '0') * k;
                    k *= 10;
                    j--;
                }
                if (j < 0 || s1[j] == '+') xs2 += u;
                else if (s1[j] == '-') xs2 -= u;
            }
            
        } else if (s1[i] == 'x' && s1[i + 1] == '^') {
            if (i == 0 || s1[i - 1] == '+') xs1++;
            if (i > 0 && s1[i - 1] == '-') xs1--;
            if (i > 0) {
                int j = i - 1;
                int u = 0, k = 1;
                while (j >= 0 && s1[j] >= '0' && s1[j] <= '9') {
                    u = u + (s1[j] - '0') * k;
                    k *= 10;
                    j--;
                }
                if (j < 0 || s1[j] == '+') xs1 += u;
                else if (s1[j] == '-') xs1 -= u;
            }
        }
    int i = 0;
    while (i < s1.size())
        if (s1[i] >= '0' && s1[i] <= '9' && s1[i - 1] != '^') {
            int j = i;
            int u = 0;
            while (s1[j] >= '0' && s1[j] <= '9') {
                u = u * 10 + s1[j] - '0';
                j++;
            }

            if (s1[i - 1] == '-') u = -u;
            if (s1[j] != 'x') cs += u;
            i = j;
        } else i++;
}
int main() {
    string s;
    cin >> s;
    string s0 = "", s2 = "";
    int n = s.size();
    for (int i = 0; i < s.size(); i++)
        if (s[i] == '=') {
            for (int j = 0; j < i; j++)
                s0 = s0+(char)s[j];
            for (int j = i+1; j < s.size(); j++)   
                s2 = s2+(char)s[j];
            break;
        }
    int r = 0,  p = 0, g = 0;
    js(s0, r, p, g);
    int aa = 0, bb = 0, cc = 0;
    js(s2, aa, bb, cc);
    int a = r - aa;
    int b = p - bb;
    int c = g - cc;
    int delta = b*b-4*a*c;
    double x1 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a);
    double x2 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
    int a1 = (int)x1;
    int a2 = (int)x2;
    int aa1 = abs((int)((x1-a1)*1000));
    int aa2 = abs((int)((x1-a1)*1000));
    if (aa1 > 0 && aa1 %10 >= 5) aa1 +=10;
    if (aa2 > 0 && aa2 %10 >= 5) aa2 +=10;
    if (aa1 < 0 && (-aa1)% 10 >= 5) aa1 -= 10;
    if (aa2 < 0 && (-aa2)% 10 >= 5) aa2 -= 10;
    cout << a1 << '.' << abs(aa1)/10 << ' ';
    cout << a2 << '.' << abs(aa2)/10 << '\n';
    return 0;
}


发表于 2023-03-20 15:49:39 回复(0)
//将所有变量和常量都移到等式左边,得到aX^2+bX+c=0,在用公式做
#include "stdio.h"
#include "math.h"
#include "string"
#include "iostream"
#include "algorithm"
using namespace std;
string str;

int calculate(int pos){//计算x^2,x前的数字(num1,num2)的位数
    int count = 0;
    for (int i = pos-1; i >= 0; --i) {
        if (str[i] >= '0' && str[i] <= '9'){
            ++count;
            continue;
        } else
            break;
    }
    ++count;
    return count;
}

int calculate2(int pos){//计算普通数字num3的位数
    int count = 0;
    for (int i = pos; str[i] >= '0' && str[i] <= '9'; ++i) {
        ++count;
    }
    return count;
}

int main(){
    ;int sum1=0,sum2=0,sum3=0;//sum1为x^2系数,sum2为x系数,sum3为常数(都移到方程左侧)
    while (getline(cin,str)){
        /*
         * 对str初始化,对x,x^2变成1x,1x^2,开头的再变成+/-1x,+/-x^2,相当于规格化,便于后续处理
         */
        for (int i = 0; i < str.size(); ++i) {//加1
            if (str[i] == 'x'){
                if (str[i-1] == '+' || str[i-1] == '-' || str[i-1] == '=' || i==0){
                    str.insert(i,"1");
                    continue;
                }
            }
            if (str[i] > '0' && str[i] <= '9'){
                if (str[i-1] == '=' || i == 0){
                    str.insert(i,"+");
                    continue;
                }
            }
        }
        if (str[1] == 'x')//加"+"
            str.insert(0,"+");
        int pos_equal = str.find("=");
        if (str[pos_equal+2] == 'x')
            str.insert(pos_equal+1,"+");
        while (str.find("x^2")!=string::npos){//算出sum1 ->a
            int pos = str.find("x^2");
            int count = calculate(pos);
            if (pos < pos_equal){
                sum1 += stoi(str.substr(pos-count,count));
                str.erase(pos-count,count+3);
            } else{
                sum1 -= stoi(str.substr(pos-count,count));
                str.erase(pos-count,count+3);
            }
            pos_equal = str.find("=");
        }
        while (str.find("x") != string::npos){//算sum2 ->b
            int pos = str.find("x");
            int count = calculate(pos);
            if (pos < pos_equal){
                sum2 += stoi(str.substr(pos-count,count));
                str.erase(pos-count,count+1);
            } else{
                sum2 -= stoi(str.substr(pos-count,count));
                str.erase(pos-count,count+1);
            }
            pos_equal = str.find("=");
        }
        for (int i = 0; i < str.size(); ++i) {//算num3
            if (str[i] > '0' && str[i] <= '9'){
                int count = calculate2(i);
                if (i < pos_equal){
                    sum3 += stoi(str.substr(i-1,count+1));
                    str.erase(i-1,count+1);
                } else{
                    sum3 -= stoi(str.substr(i-1,count+1));
                    str.erase(i-1,count+1);
                }
                pos_equal = str.find("=");
            }
        }
        double temp = sum2*sum2*1.0-4*sum1*sum3;
        if (temp<0)
            printf("No Solution\n");
        else{
            double x = (-sum2 - sqrt(temp))/(2*sum1);
            double y = (-sum2 + sqrt(temp))/(2*sum1);
            if (x > y)
                swap(x,y);
            printf("%.2llf %.2llf\n",x,y);
        }
    }
}

发表于 2023-03-13 19:01:17 回复(0)
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <cstring>

using namespace std;

int main(){
    string str;
    int a1 = 0, b1 = 0, c1 = 0;  //左边系数
    int a2 = 0, b2 = 0, c2 = 0;  //右边系数
    while(cin >> str){
        int len = str.size();
        bool right = false;  //判断等式左右
        bool Symbol = true;  //+号为true,-号为false
        int temp = 0;
        for(int i = 0; i < len; i++){
            if(!right){  //等式左边
                if(str[i] == '='){
                    if(temp != 0){
                        c1 = temp;
                        if(!Symbol) c1 = -c1;
                        temp = 0;
                    }
                    right = true;
                    Symbol = true;
                }
                else if(isdigit(str[i])) temp = 10 * temp + str[i] - '0';
                else if(str[i] == '+' || str[i] == '-') Symbol = str[i] == '+';
                else if(str[i] == 'x'){
                    if(temp == 0) temp = 1;
                    if(i + 1 < len && str[i + 1] == '^'){
                        a1 = temp;
                        if(!Symbol) a1 = -a1;
                        i += 2;
                    }
                    if(i + 1 < len && str[i + 1] != '^'){
                        b1 = temp;
                        if(!Symbol) b1 = -b1;
                    }
                    temp = 0;
                }
            }else{  //等式右边
                if(isdigit(str[i])) temp = 10 * temp + str[i] - '0';
                else if(str[i] == '+' || str[i] == '-') Symbol = str[i] == '+';
                else if(str[i] == 'x'){
                    if(temp == 0) temp = 1;
                    if(i + 1 < len && str[i + 1] == '^'){
                        a2 = temp;
                        if(!Symbol) a2 = -a2;
                        i += 2;
                    }
                    if(i + 1 < len && str[i + 1] != '^'){
                        b2 = temp;
                        if(!Symbol) b2 = -b2;
                    }
                    temp = 0;
                }
            }
        }
        if(temp != 0){
            c2 = temp;
            if(!Symbol) c2 = -c2;
        }
        double x1, x2, temp1, temp2;
        a1 -= a2;
        b1 -= b2;
        c1 -= c2;
        temp1 = b1 * b1 - 4 * a1 * c1;
        if(temp1 < 0) printf("No Solution\n");
        else{
            temp2 = sqrt(temp1);
            x1 = (-b1 + temp2) / 2 / a1;
            x2 = (-b1 - temp2) / 2 / a1;
            if(x1 < x2) printf("%.2lf %.2lf\n", x1, x2);
            else printf("%.2lf %.2lf\n", x2, x1);
        }
    }
    return 0;
}
发表于 2022-03-05 14:02:13 回复(0)
#include"iostream"
#include"math.h"
#include"iomanip"
using namespace std;
struct equation{
    int a, b, c;
    equation(int aa, int bb, int cc):a(aa), b(bb), c(cc){}
    equation(){}
};
equation getCoff(string ipt, int equ){// 自左向右扫描串 
    equation e(0, 0, 0);              // 根据数字,+,-,x,^调整临时系数对应的符号,次数,值
    int flag= 1, temp= 0, power= 0;   // 每次扫描后查看是否进行系数的更新
    for(int i= 0; i< ipt.length(); i++){
        if(ipt[i]== '+'|| ipt[i]== '-'){flag= ipt[i]== '+'? 1: -1;}
        else if(isdigit(ipt[i])){temp= temp* 10+ ipt[i]- '0';}
        else if(ipt[i]== 'x'){power++;}
        else if(ipt[i]== '^'){power= power- 1+ ipt[i+ 1]- '0'; i++;}
        if(i+ 1== ipt.length()|| ipt[i+ 1]== '+'|| ipt[i+ 1]== '-'){
            if(power== 0){e.c+= temp* flag* equ;}
            else if(power== 1){temp= (temp== 0? 1:temp); e.b+= temp* flag* equ;}// 防止一次项系数为1的情况
            else{temp= (temp== 0? 1:temp); e.a+= temp* flag* equ;}// 防止二次型系数为1的情况
            flag= 1, temp= 0, power= 0;// 初始化临时系数的符号,值,次数
        }
    }
    return e;
}
void killRoot(equation e){// 求根
    float deta= (pow(e.b, 2)- 4*e.a*e.c);// b^2- 4ac
    if(deta>= 0){
        float r1= (-e.b -sqrt(deta))/(2* e.a* 1.0), r2= (-e.b +sqrt(deta))/ (2* e.a* 1.0);
        cout<< fixed<< setprecision(2)<< min(r1, r2)<< " "<< max(r1, r2)<< endl;
    }else{
        cout<< "No Solution"<< endl;
    }
}
int main(){

    string ipt;
    while(getline(cin, ipt)){
        int idx= ipt.find('=');    // 确定等号
        string left= ipt.substr(0, idx);// 分解等式
        string right= ipt.substr(idx+ 1);
        equation e1= getCoff(left, 1);// 获取等式左侧的二次式系数
        equation e2= getCoff(right, -1);// 获取等式右侧的二次式系数
        equation e(e1.a+ e2.a, e1.b+ e2.b, e1.c+ e2.c);// 完整的二次式系数
        killRoot(e);// 求解
    }
}

发表于 2021-05-03 10:56:38 回复(0)
//以等号为边界,找到两边的系数再进行计算
//找系数过程:找到数字,看后面是x、x^2还是其他
//注意测试案例全部先输出较小的根

#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<iomanip>

using namespace std;

vector<int> count(int begin, int end, string str){
    vector<int> num(3, 0);
    int tmp=0;
    int op=0;
    
    for(int i=begin; i<=end; i++){
        if(str[i]>='0' && str[i]<='9'){
            //判断数字的符号
            if(i==begin || str[i-1]=='+') op=1;
            else if(str[i-1]=='-') op=-1;
            
            //数字可能有多位,连续读入
            tmp=str[i]-'0';
            while(str[i+1]>='0' && str[i+1]<='9'){
                i++;
                tmp=tmp*10+str[i]-'0';
            }
            
            tmp*=op;//乘上符号
            
            
            if(i==end) num[2]+=tmp;//最后一位是数字,肯定是常数项
            //后面一位是x
            else if(str[i+1]=='x'){
                i++;//跳过这个x
                if(i+1==end) num[1]+=tmp;//最后一位是x,肯定是一次项
                else if(str[i+1]=='^') {//二次项
                    num[0]+=tmp;
                    i+=2;//跳过^x
                }
                else num[1]+=tmp;//数字后面不是^2,则是一次项
            }
            else num[2]+=tmp;//数字后面不是x,则是常数项
        }
    }
    return num;
}


int main(){
    string str;
    vector<int> left(3), right(3);
    double a, b, c, tmp;
    double x1, x2, deta;
    
    while(cin>>str){
        //对x^2,x这种隐藏系数1的进行补充
        for(int i=0; i<str.size(); i++){
            if(str[i]=='x'){
                if(i==0){
                    str.insert(str.begin()+i, '1');
                    i++;
                }
                else if(str[i-1]<'0' || str[i-1]>'9'){
                    str.insert(str.begin()+i, '1');
                    i++;
                }
            }
        }
        
        int index=str.find('=');
        
        left=count(0, index-1, str);//等号左边系数
        right=count(index+1, str.size()-1, str);//等号右边系数
        
        a=left[0]-right[0];
        b=left[1]-right[1];
        c=left[2]-right[2];
        
        //计算根
        deta=b*b-4*a*c;
        if(deta<0) cout<<"No Solution"<<endl;
        else{
            x1=(-sqrt(deta)-b)/(2*a);
            x2=(sqrt(deta)-b)/(2*a);
            if(x1>x2) swap(x1, x2);//为了AC,先输出小的根
            cout<<fixed<<setprecision(2)<<x1<<' '<<x2<<endl;
        }
    }
    
    return 0;
}

发表于 2021-03-11 23:32:43 回复(0)
Java解法
1. 首先将-都替换为+- (这样可以保留负数);
2. 以=为分割符分割为左右半边;
3. 左右半边以+为分割符,分别分成若干个未知数例如5x^2
4. 提取左右半边系数,然后移项后得a,b,c
5. 利用(-b+-(b^2-4ac))/2a进行求解
(其中要注意 double保留两位小数,以及判断是否有解)
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * 
 * 求解 5x^2+x=3x+4
 * 求根公式 (-b+—(b^2-4ac))/2a
 * @author csidez
 *
 */
public class Main {
	//解析未知数的系数
	void solveArray(String[] array, Map<String, Integer> map) {
		for (int i=0; i<array.length; i++) {
			if (array[i].contains("x^2")) {
				String num = array[i].substring(0, array[i].indexOf("x^2"));
				map.merge("x^2", num.equals("")?1:Integer.parseInt(num), (oldV, newV)->oldV+newV);
			} else if (array[i].contains("x")) {
				String num = array[i].substring(0, array[i].indexOf("x"));
				map.merge("x", num.equals("")?1:Integer.parseInt(num), (oldV, newV)->oldV+newV);
			} else {
				map.merge("C", array[i].equals("")?0:Integer.parseInt(array[i]), (oldV, newV)->oldV+newV);
			}
		}
	}
	
	public static void main(String args[]) {
		Scanner scanner = new Scanner(System.in);
		Main fc = new Main();
		String line[] = scanner.nextLine().replace("-", "+-").split("\\=");
		String left[] = line[0].split("\\+");
		String right[] = line[1].split("\\+");
		Map<String, Integer> lmap = new HashMap<String, Integer>();
		Map<String, Integer> rmap = new HashMap<String, Integer>();
		fc.solveArray(left, lmap);
		fc.solveArray(right, rmap);
	
		double a = lmap.getOrDefault("x^2", 0) - rmap.getOrDefault("x^2", 0);
		double b = lmap.getOrDefault("x", 0) - rmap.getOrDefault("x", 0);
		double c = lmap.getOrDefault("C", 0) - rmap.getOrDefault("C", 0);
		
		double k = Math.sqrt(b*b-4*a*c);
		if (b*b-4*a*c < 0) {
			System.out.println("No Solution");
		} else {
			System.out.println(String.format("%.2f", (-b+k)/(2*a)) + " " + String.format("%.2f", (-b-k)/(2*a)));
		}
	}
}


发表于 2021-03-03 16:35:42 回复(0)
//这个题的关键是提取出一元二次方程的abc,然后用公式计算即可,注意数学式子的隐含部分,分别是式子开头(包括等号后面第二部分开头)隐含的正号,无系数x和x^2前隐含的系数1,只有系数情况下隐含的x^0次数项
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>

 
using namespace std;


int turn(int a)
{
    int count=0;
    while(a!=0)
    {
        count*=10;
        count+=a%10;
        a/=10;
    }
    
    return count;
}

 
int main(int argc, char** argv) {
    int n,m;
    int i,j;
    char s[100];
    string str;
    int data2,data1,data0;
    //char data[100];
    while(getline(cin,str))
    {
        
        //提取a,b,c 
        data2=data1=data0=0;
        int temp=0;
        int sign=1;
        int dsign=1;
        for(i=0;i<str.length();i++)
        {
            if(str[i]>='0'&&str[i]<='9')  //提取数字 
            {
                temp*=10;
                temp+=(str[i]-'0');
            }
            else if(str[i]=='x')  //x项(一次项和二次项的处理) 
            {
                if(temp==0)temp=1;  //隐含系数单独处理 
                if(str[i+1]=='^'&&str[i+2]=='2')
                {
                    data2+=dsign*sign*temp;
                    temp=0;
                    i+=2;
                }
                else
                {
                    data1+=dsign*sign*temp;
                    temp=0;
                }
            }
            else if(str[i]=='+')dsign=1;
            else if(str[i]=='-')dsign=-1;
            else if(str[i]=='=')  //等号两侧要变换符号,通过一次扫描把原式整理成一般式,并提取出一元二次方程的abc 
            {
                data0+=dsign*sign*temp;
                dsign=1;  //重置数字符号位 
                sign=-sign;
            }
        }
        if(temp!=0)data0+=dsign*sign*temp;  //隐含零次项单独处理 
        
        cout<<data2<<" "<<data1<<" "<<data0<<endl;
        
        //计算一元二次方程的两个解 
        int delta=data1*data1-4*data2*data0;
        if(delta<0)cout<<"No Solution"<<endl;
        else 
        {
            double x1=(-(double)data1-sqrt((double)delta))/(2*(double)data2);
            double x2=(-(double)data1+sqrt((double)delta))/(2*(double)data2);
            
        
            if(x2>x1)printf("%0.2lf %0.2lf\n",x1,x2);        //第十个测试用例在正常情况下是会输出-0.00的,因为实际上x2是一个负数,但保留两位小数使后面的小数值被省略了 
            else printf("%0.2lf %0.2lf\n",x2,x1);
            
        }
    }
    
   
    return 0;
}

发表于 2021-03-02 20:58:24 回复(0)

问题信息

难度:
54条回答 10775浏览

热门推荐

通过挑战的用户

查看代码