码迷,mamicode.com
首页 > 其他好文 > 详细

新 四则运算

时间:2016-09-14 23:08:39      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<math.h>
using namespace std;
#define EPS 1e-5
char s[50];
int val[300];
void gao(char str[])//把中缀表达式转换成后缀 
{
	 int cnt  = 0;
     stack<int> st;//符号栈 
	 int len = strlen(str);
	 for(int i = 0;i<len;i++)
	 {
 		if(str[i]==‘(‘) st.push(str[i]);//对左括号的处理
 		else if(str[i]==‘)‘)//对右括号的处理 
 		{
 	          while(!st.empty())
 	          {
          	 	   int u = st.top();
          	 	   st.pop();
          	 	   if(u==‘(‘) break;
          	 	   s[cnt++] = u;
          	  }
	    }
	    else if(str[i]==‘+‘||str[i]==‘-‘||str[i]==‘*‘||str[i]==‘/‘)//对运算符的处理 
	    {
    		while(!st.empty())
    		{
		    	int u = st.top();
		    	if(u==‘(‘||val[str[i]]>val[u]) break;
		    	st.pop();
		    	s[cnt++] = u;
		    }
		    st.push(str[i]);
    	}
    	else//数字直接加入字符串 
    	{
	    	s[cnt++] = str[i];
	    }
	    
 	 }    
 	 //把还在栈中的符号出栈 
 	 while(!st.empty())
 	 {
 	 	int u = st.top();
 	 	st.pop();
 	 	s[cnt++]  = u;
 	 }
 	 s[cnt] = 0;
}
int gcd(int a,int b)//求最大公约数 
{
	return b==0? a:gcd(b,a%b);
}
int lcm(int a,int b)//求最小公倍数 
{
	return a*b/gcd(a,b);
}
pair<int,int> cal(char str[])//计算值,已分数表示 
{
	
	int a,b;
	stack<pair<int,int> > st;//存放值的栈,用分数表示 
	int len = strlen(str);
	for(int i = 0;i<len;i++)
	{
		if(str[i]>=‘0‘&&str[i]<=‘9‘)
		{
			st.push(make_pair(str[i]-‘0‘,1));//现转化为分数 
		}
		else
		{
			pair<int,int> pa1 = st.top();
			st.pop();
			pair<int,int> pa2 = st.top();
			st.pop();
			int LCM = lcm(pa1.second,pa2.second);
			if(str[i]==‘+‘)//对加法的处理 
			{
				//if(pa1.second==0||pa2.second==0) return make_pair(0,0);
				int a = pa1.first*(LCM/pa1.second);
				int b = pa2.first*(LCM/pa2.second);
				pa1.first = a+b;
				pa1.second = LCM;
				st.push(pa1);//入栈 
			}
			else if(str[i]==‘-‘)//对减法的处理 
			{
			    int a = pa1.first*(LCM/pa1.second);
				int b = pa2.first*(LCM/pa2.second);
				pa1.first = b-a;
				pa1.second = LCM;
				st.push(pa1);
			}
			else if(str[i]==‘*‘)//对乘法的处理 
			{
		        pa1.first = pa1.first*pa2.first;
				pa1.second = pa1.second*pa2.second;
				st.push(pa1);
				
			}
			else//对除法的处理 
			{
				if(pa1.first==0) return make_pair(0,0);//改进了对除0的处理 
				int a = pa2.first*pa1.second;
				int b = pa2.second*pa1.first;
				pa1.first = a,pa1.second = b;
				st.push(pa1);
			} 
		}
	}
	pair<int,int> pa = st.top();
	st.pop();
	int GCD = gcd(pa.first,pa.second);
	pa.first/=GCD,pa.second/=GCD;//化成最简形式 
	return pa;
	
}
int check(char str[])//判断str字符串是否合法 
{
	int a = 0;
	int len = strlen(str);
	for(int i = 0;i<len;i++)
	{
		if(str[i]==‘(‘) a++;
		else if(str[i]==‘)‘)a--;
		if(a<0) return 0;	
		if(str[i]==‘)‘&&i>=2&&str[i-2]==‘(‘) return 0;
	}
	if(str[0]==‘(‘&&str[strlen(str)-1]==‘)‘) return 0;
	return 1;
}

int ok(int a,int b,char str[])	//判断在str的ab位置放括号的合法性 
{
   if(str[a]<‘0‘||str[b]<‘0‘||str[a]>‘9‘||str[b]>‘9‘) return 0;
   if(b<=a) return 0;
   if(a==0&&b==strlen(str)-1) return 0;
   if(a!=0&&str[a-1]==‘(‘&&str[b+1]==‘)‘) return 0;
   return 1;
}

void pro(char str[])//随机产生一个四则运算 
{
	int sum = rand()%3;	//随机括号的个数 
	for(int i = 0;i<=6;i++)
	{
		if(i%2==0)
		{
			str[i] = rand()%9+1+‘0‘;
		}
		else
		{
			int temp = rand()%4;
			if(temp==0) str[i] = ‘+‘;
			if(temp==1) str[i] = ‘-‘;
			if(temp==2) str[i] = ‘*‘;
			if(temp==3) str[i] = ‘/‘;
		}
	}
	str[7] = 0;
	for(int i= 1;i<=sum;i++)//循环增加括号 
	{
		int a = rand()%(7+2*i-2);
		int b = rand()%(7+2*i-2);
		while(!ok(a,b,str))
		{
			a  = rand()%(7+2*i-2);
			b  = rand()%(7+2*i-2);
		}
		char ss[100];
		int cnt = 0;
		for(int j = 0;j<7+2*i-2;j++)
		{
			if(j==a)
			{
				ss[cnt++] = ‘(‘;
				ss[cnt++] = str[j];
			}
			else if(j==b)
			{
				ss[cnt++]  = str[j];
				ss[cnt++] = ‘)‘;
			}
			else ss[cnt++] = str[j];
		}
		ss[cnt] = 0;
		int flag = check(ss);
		if(!flag) i--;
		else
		{
			strcpy(str,ss);
		}
	}
  //  printf("%s\n",str);
  //  gao(str);
   // pair<int,int> pa = cal(s);
   // printf("%d %d\n",pa.first,pa.second);
}
int is_ok(int a, int b)//判断a/b是否是无限循环小数 
{
	if(b==0) return 0;
	if(a==0) return 1;
	map<int,int> ma;
	while(1)
	{
		while(a<b) a*=10;
		if(a%b==0) return 1;
		if(ma[a%b]) return 0;
		ma[a%b] = 1;
		a = a%b;
	}
	
}
void pri(int a,int b)//打印a/b的值 
{
	if(a==0)//如果为0直接输出防止后面运算出bug 
	{
		printf("0");
		return;
	}
	printf("%d.",a/b);
	a = a%b;
	//a*=10;
	while(1)
	{
		int flag = 0;
		while(a<b)
		{
			a*=10;
			if(flag)
			printf("0");
			flag++;
		}
		printf("%d",a/b);
		a = a%b;
		if(a==0) break;
	}
}
int is_num(char str[])//判断str是否为正整数 
{
	int sum = 0;
	int len = strlen(str);
	for(int i = 0;i<len;i++)
	{
		if(str[i]>=‘0‘&&str[i]<=‘9‘) sum = sum*10+str[i]-‘0‘;
		else return -1; 
	}
	if(sum==0) return -1;
	else return sum;
}
int main(int argc,char *argv[10])
{
	srand(time(0));//初始化随机种子 
    val[‘+‘] = val[‘-‘] = 1;
    val[‘*‘] = val[‘/‘] = 2;//运算符的优先级 
    if(argc==1)//功能1,2 
    {
    	int sum  = 0;
    	char str[50];
    	for(int i = 1;i<=20;i++)
    	{
	    	pro(str);
	    	gao(str);
	    
	    	pair<int,int> pa = cal(s);
	    //	printf("%s\n",str);
	        if(pa.second==0)//说明有除0现象 
	        {
        		i--;
        		continue;
        	}
	    	//printf("%d %d\n",abs(pa.first),abs(pa.second));
	    	if(is_ok(abs(pa.first),abs(pa.second)))//不能整除继续寻找 
	    	{
	    		printf("%s\n?",str);
	    	}
	    	else
	    	{
	    		i--;
	    		continue;
	    	}
    		//printf("%d %d\n",abs(pa.first),abs(pa.second));
	    	//printf("%s\n",s);
	    	double res;
	    	scanf("%lf",&res);
	    //	printf("%lf\n",res-1.0*pa.first/pa.second);
	    	if(fabs(res-1.0*pa.first/pa.second)<EPS)//eps为误差值,用于double比较 
	    	{
	    		sum++;
	    		printf("答对了,你真是个天才!\n");
	    	}
	    	else
	    	{
	    		if(abs(pa.first)%abs(pa.second)==0)//整除直接输出 
	    		{
    			   printf("在想想吧,答案似乎是%d喔!\n",pa.first/pa.second);
		    	}
		    	else
	    		{
	    			int flag = 0;
	    			if(pa.first<0) flag++;
	    			if(pa.second<0) flag++;
	    			
 		            printf("在想想吧,答案似乎是");
 		            if(flag%2==1) printf("-");
				    pri(abs(pa.first),abs(pa.second));
				    printf("喔!\n");
				    
				}
	    	}
	    	
	    }
	    printf("你一共对了%d道题,共20道题.\n",sum);
    }
    if(argc==3)//功能3,4 
    {
    	int flag  = is_num(argv[2]);
    	if(flag==-1) {printf("题目数量必须是 正整数。\n");return 0;}
    	for(int i = 1;i<=flag;i++)
    	{
	    	char str[100];
	    //	printf("111111\n");
	    	pro(str);
	    
	    	gao(str);
	    	printf("%-50s%",str);
	    //	printf("%s\n",str);
	    	pair<int,int> pa = cal(s);
			//	printf("%d 2222222\n",i); 
			
		    if(pa.second==0) {
    			i--;continue;
    		}
	    	if(pa.first%pa.second==0) printf("%d\n",pa.first/pa.second);
	    	else
	    	{
	    			int flag = 0;
	    			if(pa.first<0) flag++;
	    			if(pa.second<0) flag++;
	    			if(flag%2) printf("-");
	    			pa.first = abs(pa.first);//正负提取,取绝对值 
	    			pa.second = abs(pa.second);
	    			if(pa.first/pa.second) printf("%d ",pa.first/pa.second);
	    			pa.first-=pa.first/pa.second*pa.second;
	    			printf("%d/%d\n",pa.first,pa.second);//输出答案 
	    			
	    	}
	    //	printf("11111\n");
	    }
    	
    }
	return 0;
}

  技术分享技术分享技术分享

 

 

结对作业:李峤  杜月

新 四则运算

标签:

原文地址:http://www.cnblogs.com/liqiao085/p/5873614.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!