改良计算器(搜索)

题目背景

NCLNCL 是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能。实验室将这个任务交给了一个刚进入的新手ZL先生。

题目描述

为了很好的完成这个任务, ZLZL 先生首先研究了一些一元一次方程的实例:

4+3x=84+3x=8

6a-5+1=2-2a6a−5+1=2−2a

-5+12y=0−5+12y=0

ZLZL 先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及+、-、=这三个数学符号(当然,符号“-”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。

你可假设对键入的方程的正确性的判断是由另一个程序员在做,或者说可认为键入的一元一次方程均为合法的,且有唯一实数解。

输入输出格式

输入格式:

一个一元一次方程。

输出格式:

解方程的结果(精确至小数点后三位)。

输入输出样例

输入样例#1: 复制

6a-5+1=2-2a

输出样例#1: 复制

a=0.750

思路:getchar()输入防止TCL

等式变换分别求出变量系数值以及常量值,后者除以前者得到结果、

存在很多细节的地方(看代码注释)

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;       //防止数据溢出
int main()
{
    ll local_judge=1;
    ll pos_judge=1;
    ll count=0;
    ll deno=0;
    ll ans=0;
    double result;
    char x;
    bool sym_judge=false;
    char s=getchar();
    while(1)
    {
        if(s>='a' && s<='z')            //找到未知变量
        {
           x=s;
           if(count==0 && !sym_judge)            //判断未知变量前面是否有系数
           {
               deno += pos_judge * local_judge;    //默认系数为1

           }
           else
           {
               deno += pos_judge * local_judge *count;      //等式变换求变量的系数值
               count=0;
               pos_judge=1;
               sym_judge=false;
           }
        }
        else if(s=='-')
        {
            ans  += -count * pos_judge * local_judge;   
            sym_judge=false;
            count=0;
            pos_judge=-1;                               //遇到'-',pos_judge标记-1
        }
        else if(s=='+')
        {
            ans += -count * pos_judge * local_judge;
            sym_judge=false;
            count=0;
            pos_judge=1;                                //遇到'+',pos_judge标记1
        }
        else if(s=='=')
        {
            ans += -count * pos_judge *local_judge;
            sym_judge=false;
            count=0;
            pos_judge=1;                                  //遇到'+',pos_judge标记1
            local_judge=-1;                                //local_judge标记等式右边
        }
        else if(s>='0' && s<='9')   
        {
            count = count*10+s-'0';                        //记录完整数值
            sym_judge=true;
        }
        else
        {
            ans +=-count*pos_judge*local_judge;            //最后一个是数值也不能漏掉
            break;
        }
        s=getchar();
    }
    result=double(ans)/deno;                                
    printf("%c=%.3lf",x,result==0?abs(result):result);      //c++中0除以任何数得-0,强制转换为0
    return 0;
}

下面是转发一位大佬详细的代码注释及其源代码:

(可以参考学习)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//以防万一用long long 
char x; ll coe,value,opp=1;//coe表示系数,value表示值,opp表示在等号左边还是右边 
double ans;
int main(){
    char c=getchar();//为了节省空间当然要在线 
    ll cur=0,sign=1; bool value_gotten=false;//cur为当前读入的数值,sign表示当前数值符号,value_gotten是一个标记变量,字面意思是是否读入过数值,用途下面说 
    while (true){
        if (c>='a' && c<='z'){
            x=c; if (cur==0 && !value_gotten) coe+=opp*sign,value_gotten=false; //这也是个坑点(虽然数据没有涉及),如果cur为0又读入了变量名称有两种情况:一时+0x或-0x,另一种是默认系数为1,value_gotten专门判断这两种情况 
            else coe+=opp*sign*cur,cur=0,sign=1,value_gotten=false;
        }
        else if (c=='-') value+=-opp*sign*cur,cur=0,sign=-1,value_gotten=false;//如果是减号把当前数值加入值(如果之前是变量则当前数值为0,加入也没有影响),并清空当前数值,设value_gotten为false,符号修改为负 
        else if (c=='+') value+=-opp*sign*cur,cur=0,sign=1,value_gotten=false;//加号和减号一样,只是把符号修改为正 
        else if (c>='0' && c<='9') cur=cur*10+c-'0',value_gotten=true;//如果是数字,就对cur进行计算,并把value_gotten设为true 
        else if (c=='=') value+=-opp*sign*cur,cur=0,sign=1,opp=-opp,value_gotten=false;//等号和加减号差不多,只是要把opp设为负 
        else {value+=-opp*sign*cur;break;}//最后的值累加上去 
        c=getchar();
    }
    ans=double(value)/coe;//计算ans 
    printf("%c=%.3lf",x,ans==0?abs(ans):ans);//这涉及一个很坑的地方:C++里0除以一个负数值为-0,专门避免这种情况 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq1013459920/article/details/81414874