数学小论文

这篇数学小论文探讨了计算机如何处理加减乘除和括号的运算。作者介绍了两种方法:一是使用栈来实现运算,二是通过递归的方法。文章通过实例解释了这两种方法的工作原理,并指出在实际计算中,栈实现通常更快。虽然内容不涉及高级数学定理,但深入浅出地解析了计算机基础运算的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好了,又要开始写数学小论文了。开始,本来是想写一些高大上的数学定理,但是发现其实自己根本没有理解到这个定理的本质,讲也讲不清。

所以,我决定,从最开始的东西为基础来写本次的数学小论文,那就是加减乘除(当然,还有括号),在现实生活中,这些都是十分简单的东西,是一位学生,就肯定把这简单的四则运算牢记于心。还有很多同学,利用计算器,去研究或者推测一些数学定理。

但是,又有几个人知道,在这计算机的背后,人们是用什么程序来实现四则运算以及括号的匹配的呢?今天,我就来聊一聊计算机是如何实现这一切的。

接下来,我们要推广到有加减乘除四则运算以及有括号参与的计算了。
在这里介绍两种方法:

1.用栈来实现:
首先用一个栈来存储数字,用一个栈来存储符号。
栈是什么呢,栈就像一个火车站,火车进进出出,只有一个轨道。在栈底的元素如果想出来的话,那么就必须等他上面的元素都出来之后才能出来。火车也是这样,在里面的火车必须等在外面的火车都出去了之后才能出来。期间,可能还会又新的火车进站。

如果进来的是左括号,那么先放着不做处理,如果进来的是加号和减号,就直接做到小括号为止。如果是乘号和除号,就做到第一个级别比他小的地方或者左括号为止。如果进来的是右括号,那么做到第一个左括号为止,并且删去该左括号,直到做到结束。这样在存数字的栈中唯一剩余的那一个数就是答案。

如果还是有点懵逼的童鞋可以看程序理解一下:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int maxN=100100;
const int mod=10000;
string s;
long long op1[maxN];
char op2[maxN];
int num1,num2;

void handle()
{
	switch(op2[num2]){
		case '+':
			op1[num1-1]=(op1[num1-1]+op1[num1])%mod;
			num1--; 
			break;
		case '-':
			op1[num1-1]=(op1[num1-1]-op1[num1])%mod;
			num1--;
			break;
		case '*':
			op1[num1-1]=(op1[num1-1]*op1[num1])%mod;
			num1--;
			break;
		case '/':
			op1[num1-1]=(op1[num1-1]/op1[num1])%mod;
			num1--;
			break;			
	}
}
void work1()
{
	while(num2>0&&op2[num2]!='('){
		handle();
		num2--;
	}
}

void work2()
{
	while(num2>0&&(op2[num2]=='*'||op2[num2]=='/')){
		handle();
		num2--;
	} 
} 

int main()
{
    //freopen("expr.in","r",stdin);
    //freopen("expr.out","w",stdout);
    cin>>s;
    int len=s.length();
	int i=0;
	while(i<len){
		if(s[i]<='9'&&s[i]>'0'){
			long long temp=0;
			while(i<len&&s[i]>='0'&&s[i]<='9'){
				temp=(temp*10+s[i]-'0')%mod;
				i++;
			}
			num1++;
			op1[num1]=temp;
		}
		if(i==len)
			break;
		switch(s[i]){
			case '+':
			case '-':
					work1();
					op2[++num2]=s[i];
					break;
			case '*':
			case '/':
					work2();
					op2[++num2]=s[i];
					break;
			case '(':
					op2[++num2]=s[i];
					break;
			case ')':
					work1();
					num2--; 
					break;
		}
		++i;
		cout<<num1<<endl;
		for(int i=1;i<=num1;++i)
			cout<<op1[i]<<" ";
		cout<<endl;
		cout<<num2<<endl;
		for(int i=1;i<=num2;++i)
			cout<<op2[i]<<" ";
		cout<<endl<<endl;
	}   
    work1();
    cout<<op1[1]<<endl;
    return 0;
}

2.递归
说实话,用栈来实现比用递归来实现要快多了,但是为了锻炼自己,还是要每一种方法都要写一下。
先讲一下思路吧:首先我们要找到最后一次运算的符号在哪里,并且从这分开,在他的左右两边去寻找各自区间的最后运算的符号在哪里,然后以此类推,直到这个区间所有的都是数字为止。
首先,我们要解决括号配对的问题。我们依然可以用栈的思想来实现,并且我们还要记录每一个点他外面所拥有的括号层数,以此来判断是否为最后一次运算的符号。说完思路,可能大家还是有点蒙蒙的,举一个栗子好了:
假如说我们要计算 (1+2)*3 的值
用栈将s[0]的左括号和 s[4] 的右括号匹配,那么s[1]到s[3]的外层括号数都为1

首先递归0到(len-1)寻找最后做的运算符号,发现是s[5]的乘号,所以再递归两边的最后的符号,即递归0到4,和递归6到6,将二者的值乘起来就是答案。

下面考虑6到6:由于是一个数字,所以结束递推,返回值s[6]
再来考虑0到4:由于s[0]和s[4]是一对匹配的左右括号,所以直接考虑1到3,1+2…这个就不必再往下了吧?
最后附上代码~~~

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxN=100100;
string s;
int len,ans,stack[maxN],stacknum=0,kuo[maxN],kuonum=0;
int peidui[maxN];

bool isDigit(int l,int r)
{
	for(int i=l;i<=r;++i){
		if(s[i]<'0'||s[i]>'9')
			return false;
	}
	return true;
}

int dg(int l,int r)
{
	if(isDigit(l,r)){
		int t=s[l]-'0';
		for(int i=l+1;i<=r;++i)
			t=t*10+s[i]-'0';
		return t;
	}
	if(peidui[l]==r){
		for(int i=l+1;i<=r-1;++i)
			kuo[i]--;
		return dg(l+1,r-1);
	}
	char p='.';
	int p1=-1;
	for(int i=l+1;i<=r-1;++i){
		switch(s[i]){
			case '+':
			case '-':
				if(kuo[i]==0){
					p=s[i];
					p1=i;
				}
				break;
			case '*':
			case '/':
				if(kuo[i]==0){
					if(p1==-1){
						p1=i;
						p=s[i];
					}
					else{
						if(p=='*'||p=='/'){
							p1=i;
							p=s[i];
						}
					}
				}
				break;
		}
	}
	switch(p){
		case '+':
			return dg(l,p1-1)+dg(p1+1,r);
		case '-':
			return dg(l,p1-1)-dg(p1+1,r);
		case '/':
			return dg(l,p1-1)/dg(p1+1,r);
		case '*':
			return dg(l,p1-1)*dg(p1+1,r);
	}
}

int main()
{
	cin>>s;
	len=s.size();
	for(int i=0;i<len;++i){
		if(s[i]=='('){
			stack[++stacknum]=i;
			kuonum++;
			kuo[i]=-1;
			continue;
		}
		if(s[i]==')'){
			peidui[stack[stacknum]]=i;
			peidui[i]=stack[stacknum];
			stacknum--;
			kuonum--;
			continue;
		}
		kuo[i]=kuonum;
	}
	cout<<dg(0,len-1)<<endl;
	return 0;
}

这只是简单的四则运算加上括号的匹配,还没有涉及开根,求方程,绝对值,分数等符号,其中,有一些的代码实现比四则运算简单,又有一些的实现难度是四则运算无法比拟的。
其实,计算机在四则运算的代码实现上就是一个思想,看拿一个符号是第一次做的,再考虑这个符号的左右的最后一个符号是哪个,就这么一直推下去,最终得到答案。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值