基于C++制作的分数加,减,乘,除,次幂,以及处理括号的多项式

介绍

在本文中,我们将探讨一个C++程序,该程序可以计算包含分数和幂运算的数学表达式。首先,我们将通过一系列功能强大的函数来简化和执行基本的分数运算(加、减、乘、除)。然后,我们将展示如何使用这些函数和

步骤 1: 定义分数运算函数

在我们的程序中,我们首先定义了一系列函数来执行基本的分数运算。这些函数包括:

1.1 gcd函数

该函数使用递归方式来计算两个数的最大公约数。

int gcd(int a, int b) {
	if (b == 0)
		return a;
	return gcd(b, a % b);
}

1.2 simplify函数

该函数用于简化分数,确保分母始终为正。

std::vector<int> simplify(int numerator, int denominator) {
	int divisor = gcd(std::abs(numerator), std::abs(denominator));
	numerator /= divisor;
	denominator /= divisor;

	// 确保分母为正
	if (denominator < 0) {
		numerator = -numerator;
		denominator = -denominator;
	}

	return { numerator, denominator };
}

1.3 基本数学运算函数

我们定义了函数来执行基本的分数运算,如加法、减法、乘法和除法。

std::vector<int> add(const std::vector<int>& a, const std::vector<int>& b);
std::vector<int> subtract(const std::vector<int>& a, const std::vector<int>& b);
std::vector<int> multiply(const std::vector<int>& a, const std::vector<int>& b);
std::vector<int> divide(const std::vector<int>& a, const std::vector<int>& b);

1.4 power函数

该函数用于计算分数的幂。

std::vector<int> power(const std::vector<int>& a, int n);

步骤 2: 解析和计算表达式

在第二部分中,我们定义了一个calc函数,它可以解析和计算含有基本数学运算符和括号的表达式。

2.1 初始化

我们首先初始化了几个栈来存储数字和运算符,并对输入字符串进行了一些预处理。

vector<int>calc(string s)
{
	char c;//符号
	vector<int> a, b, val;//左操作数、右操作数、计算结果
	stack<vector<int>> num;//存数字
	stack<char> op;//存操作符

	//以+或-开头,在开头补零
	if (s[0] == '+' || s[0] == '-')
	{
		s = "0" + s;
	}
	//将第一个数字压入分数栈
	stringstream ss(s);
	int t1;
	ss >> t1;
	val.push_back(t1);
	val.push_back(1);
	num.push(val);
	//每次读取一个符号和数字
	while (ss >> c >> val[0])
	{
		//如果符号是*/,直接与前面的数计算,消去*/
		if (c == '*' || c == '/')
		{
			if (c == '*')
			{
				val = multiply(val, num.top());
			}
			else
			{
				val = divide(num.top(), val);
			}
			
			num.pop();//弹出已经计算过的数
			num.push(val);//压入计算后的结果
			val[1] = 1;
		}
		else//符号是+-
		{
			//将取到的数和符号压栈,op栈中只留+-
			num.push(val);
			op.push(c);
		}
	}
	//操作符栈不为空,只有加减运算
	while (!op.empty())
	{
		a = num.top();
		num.pop();
		b = num.top();
		num.pop();
		if (op.top() == '+')
		{
			num.push(add(a,b));
		}
		else
		{
			num.push(subtract(b,a));
		}
		op.pop();
	}
	return num.top();
}

2.2 处理乘法和除法

我们使用一个循环来读取每个字符,并用条件语句来处理乘法和除法运算。

if (c == '*' || c == '/') {
    ...
}

2.3 处理加法和减法

接着我们处理加法和减法运算。

else {
    ...
}

2.4 计算剩余的加减运算

在循环结束后,我们计算栈中剩余的加减运算。

while (!op.empty()) {
    ...
}

步骤 3: 主函数

最后,在主函数中,我们使用一个无限循环来读取用户的输入,并调用我们之前定义的calc函数来计算表达式的结果。

3.1 处理幂运算

我们首先处理输入字符串中的幂运算。

while (1) {
    ...
    for (int i = 0; i < str.size(); i++) {
        if (str[i] == '^') {
            ...
        }
    }
    ...
}

3.2 处理括号

然后,我们使用一个循环和一个栈来处理表达式中的括号。

stack<int> kuohao;
int len = str.size();
int from, to;
for (int i = 0; i < len; i++) {
    ...
}

3.3 输出结果

最后,我们调用calc函数来计算最终的结果,并将结果输出到控制台。

vector<int> result = calc(str);
cout << result[0] << endl;
if (result[1] != 1) {
    cout << "----" << endl;
    cout << result[1] << endl;
}

步骤4:源代码

#include<iostream>
#include<string>
#include<sstream>
#include<stack>
#include<algorithm>
#include<vector>
using namespace std;
int gcd(int a, int b) {
	if (b == 0)
		return a;
	return gcd(b, a % b);
}

std::vector<int> simplify(int numerator, int denominator) {
	int divisor = gcd(std::abs(numerator), std::abs(denominator));
	numerator /= divisor;
	denominator /= divisor;

	// 确保分母为正
	if (denominator < 0) {
		numerator = -numerator;
		denominator = -denominator;
	}

	return { numerator, denominator };
}

std::vector<int> add(const std::vector<int>& a, const std::vector<int>& b) {
	int numerator = a[0] * b[1] + b[0] * a[1];
	int denominator = a[1] * b[1];
	return simplify(numerator, denominator);
}

std::vector<int> subtract(const std::vector<int>& a, const std::vector<int>& b) {
	int numerator = a[0] * b[1] - b[0] * a[1];
	int denominator = a[1] * b[1];
	return simplify(numerator, denominator);
}

std::vector<int> multiply(const std::vector<int>& a, const std::vector<int>& b) {
	int numerator = a[0] * b[0];
	int denominator = a[1] * b[1];
	return simplify(numerator, denominator);
}

std::vector<int> divide(const std::vector<int>& a, const std::vector<int>& b) {
	int numerator = a[0] * b[1];
	int denominator = a[1] * b[0];
	return simplify(numerator, denominator);
}
std::vector<int> power(const std::vector<int>& a, int n) {
	if (n == 0) {
		return { 1, 1 }; // 任何数的0次方都是1
	}
	else if (n > 0) {
		return multiply(a, power(a, n - 1));
	}
	else {
		std::vector<int> reciprocal = { a[1], a[0] };
		return power(reciprocal, -n);
	}
}
vector<int>calc(string s)
{
	char c;//符号
	vector<int> a, b, val;//左操作数、右操作数、计算结果
	stack<vector<int>> num;//存数字
	stack<char> op;//存操作符

	//以+或-开头,在开头补零
	if (s[0] == '+' || s[0] == '-')
	{
		s = "0" + s;
	}
	//将第一个数字压入数字栈
	stringstream ss(s);
	int t1;
	ss >> t1;
	val.push_back(t1);
	val.push_back(1);
	num.push(val);
	//每次读取一个符号和数字
	while (ss >> c >> val[0])
	{
		//如果符号是*/,直接与前面的数计算,消去*/
		if (c == '*' || c == '/')
		{
			if (c == '*')
			{
				val = multiply(val, num.top());
			}
			else
			{
				val = divide(num.top(), val);
			}
			
			num.pop();//弹出已经计算过的数
			num.push(val);//压入计算后的结果
			val[1] = 1;
		}
		else//符号是+-
		{
			//将取到的数和符号压栈,op栈中只留+-
			num.push(val);
			op.push(c);
		}
	}
	//操作符栈不为空,只有加减运算
	while (!op.empty())
	{
		a = num.top();
		num.pop();
		b = num.top();
		num.pop();
		if (op.top() == '+')
		{
			num.push(add(a,b));
		}
		else
		{
			num.push(subtract(b,a));
		}
		op.pop();
	}
	return num.top();
}

int main()
{
	while (1) {

		string str;//表达式字符串
		getline(cin, str);
		for (int i = 0; i < str.size(); i++) {
			if (str[i] == '^') {
				int begin1 = i - 1, end1 = i + 1;
				while (isdigit(str[end1]) && end1 < str.size()) {
					end1++;
				}
				if (isdigit(str[begin1])) {
					while (isdigit(begin1) && begin1 >= 0) {
						begin1--;
					}
					int num1 = stoi(str.substr(begin1, i - begin1));
					int num2 = stoi(str.substr(i + 1, end1 - i));
					string swap1;
					swap1 += to_string(num1);
					for (int i = 0; i < num2 - 1; i++) {
						swap1 += "*";
						swap1 += to_string(num1);
					}
					str.erase(begin1, end1 - begin1 + 1);
					str.insert(begin1, swap1);
				}
				else if (str[begin1] == ')') {
					int ju = 1;
					begin1--;
					while (begin1 >= 0) {
						if (str[begin1] == ')') {
							begin1--;
							ju++;
						}
						else if (str[begin1] == '(') {
							begin1--;
							ju--;
						}
						else {
							begin1--;
						}
						if (ju == 0) {
							begin1++;
							break;
						}
					}
					string num1 = str.substr(begin1, i - begin1);
					int num2 = stoi(str.substr(i + 1, end1 - i));
					string swap1;
					swap1 += num1;
					for (int i = 0; i < num2 - 1; i++) {
						swap1 += "*";
						swap1 += num1;
					}
					str.erase(begin1, end1 - begin1 + 1);
					str.insert(begin1, swap1);
				}

			}
		}
		for (int i = 0; i < str.size() - 1; i++) {
			if (str[i] == ')' && str[i + 1] == '(') {
				str.insert(i+1, "*");
			}
		}
		cout << str << endl;
		stack<int> kuohao;//存括号
		int len = str.size();
		int from, to;
		for (int i = 0; i < len; i++)
		{
			if (str[i] == '(' || str[i] == ')')
			{
				//括号不匹配
				if (kuohao.empty() || str[i] == str[kuohao.top()])
				{
					kuohao.push(i);//栈里存放的是'('')'在str中的index
				}
				else//括号匹配
				{
					from = kuohao.top();
					to = i; //定位到一组()
					kuohao.pop();//计算过的出栈
					//求解括号中的表达式
					vector<int> tmp = calc(str.substr(from + 1, to - from - 1));
					//把所求结果替换掉括号部分的表达式
					stringstream ss;
					ss << tmp[0];
					ss << "/";
					ss << tmp[1];
					string tmpS;
					ss >> tmpS; //double->string
					str.replace(str.begin() + from, str.begin() + to + 1, tmpS.begin(), tmpS.end());//'('...')'之间有to-from+1个字符!
					len = str.size();//循环条件记得更新
					i = from - 1;
				}
			}
		}
		vector<int> result = calc(str);
		cout << result[0] << endl;
		if (result[1] != 1) {
			cout << "----" << endl;
			cout << result[1] << endl;
		}
	}
}

结论

通过这篇文章,我们已经学会了如何创建一个能够处理复杂数学表达式的C++程序。通过使用栈数据结构和递归,我们能够轻松地解析和计算包含分数、幂运算和括号的表达式。希望你找到这篇文章有用!

最后感谢@zdluffy的文章

笔试题 C++ 利用栈实现带括号的加减乘除_c++里面乘法带括号不-CSDN博客

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值