C++实现 20位有效数字加减乘除运算

该博客详细介绍了使用C++设计的计算器,具备处理20位有效数字的加减乘除运算能力。计算器采用三层架构,包括显示层、数据转换层和计算层。数据转换模块将用户输入的字符串转换为结构体,算法模块进行计算,辅助处理模块处理数据,输出模块展示结果。整个设计包括输入验证、数据转换、算法实现和结果显示等功能模块。

2.整体架构
2.1架构图
在这里插入图片描述

图2.1计算机架构图

此计算器架构一共分为三层,显示层,数据转换层,计算层。
显示层包含输入模块和输出模块,用于与用户交互。数据转换层包含数据转换模块,用于对输入合法数据的预处理,和计算结束的后处理。 计算层包含算法模块和辅助处理模块,方便计算的复用和抽象拓展。
显示层向数据转换层传递的合法输入字符串并接收数据转换层传递而来计算结果结构体。计算层接收数据转换层传递而来的合法数据结构体并将计算结果结构体传递给数据转换层。
2.2模块设计
1.输入模块
获取用户输入的字符串,判断数字,运算符是否合法。如果不合法进行提示并重新输入;如果合法则将数据传给数据转换模块。
2.输出模块
接收到结果字符串,根据字符串长度与应取有效位数,确定显示方式。
3.数据转换模块
将输入模块传递而来的合法字符串转为合法结构体输出给算法模块;将算法模块传递而来的结果结构体,转换为结果字符串,传给输出模块。
4.算法模块
接收结构体,根据接收到的运算符,进行相应计算。根据计算需求,调用辅助模块对结构体进行预处理或后处理。输出结果结构体。
5.辅助处理模块
接收数据结构体,进行分割或者取50位数字精度,返回算法模块。
2.3流程设计
1.输入模块获取用户输入的字符串进行判断,如不合法进行提示并需要重新输入;合法则将字符串传递据转换模块。
2.数据转换模块将合法字符串转换为结构体,将转换后的结构体传递给算法模块。
3.算法模块开始计算,当结构体中数字字符串需要分割,或者需要取得50位的计算结果时,将结构体传递给辅助处理模块。
4.辅助处理模块将数据处理结束后,返回处理后的结构体。
5.算法模块继续计算,结束后得到计算结果结构体,传给数据转换模块。
6.数据转换模块将计算结果结构体转换为计算结果字符串并传给输出模块。
7.输出模块判断结果字符串,根据字符串有效位数来判断显示方式。

3.模块分解
3.1程序中所用结构体
struct bigNum
{
string num; //有效位字符串
int digit; //偏移量
int minus; //符号位(0为正,1为负)
};
以科学计数法形式记录数据,用于存储计算数据和加减乘除计算。
例:12.45 -->{
Num = “1245”;
Digit = 1;
Minus = 0;
}

3.2输入功能模块
3.2.1概述及流程图
在这里插入图片描述

图3.2.1 输入模块流程图

获取用户输入的字符串后,判断用户输入的字符串是否合法,若不合法,进行提示并重新输入;若合法将输入的字符串保存,然后进行下一个字符串的输入。直到用户成功输入三次合法字符串,输入结束。

输入模块
功能 获取用户输入数据,判断输入内容是否合法,若不合法,进行提示并重新输入;若合法输入模块输出合法字符串。
输入 由用户输入的两个计算数据及运算符
输出 用于计算的合法字符串及运算符

3.2.2模块相关函数
(1)运行计算器函数(接口函数)

在这里插入图片描述

图3.2.2(1) 运行计算器流程图

用户调用运行运行计算器函数后,获取用户输入的字符串,判断用户输入的字符串是否合法若不合法则重新输入。若合法,则继续运行。其次判断是否成功输入3次,若没有成功则返回重新输入。成功后,调用转结构体函数,将用户输入的两个计算数据字符串转换为结构体,然后调用计算函数获取结果结构体,再然后调用转字符串函数将结果结构体转为字符串,最后调用显示函数显示最终结果。

运行计算器函数
函数 bool runCalculator()
功能 获取用户输入的字符串,并调用相关函数进行运算,输出结果。
输入 无
输出 显示结果字符串

(2)判断字符串函数

在这里插入图片描述

图3.2.2 判断字符串流程图

将用户输入的字符串作为参数传入函数,判断字符串是否非法(长度是否超过50或者为空),若非法提示错误并返回false,合法则继续运行。
判断需要判断字符串类型,若字符串为运算符则判断运算符是否非法(是否为‘+’,‘-’,‘*’,‘/’中字符),若非法提示错误并返回false,合法则返回true。
若字符串为计算数据,则判断计算数据是否非法(第一个字符是否为‘+’,‘-’,‘0’-‘9’,‘.’中字符,其余字符是否为‘0’-‘9’,‘.’中字符,‘.’是否只出现一次,是否有‘0’-‘9’字符出现)若非法提示错误并返回false,合法则返回true。

判断字符串函数
函数 bool strIllegal(string num,int type)
功能 判断字符串内容是否合法
输入 Num为用户输入的字符串
type为字符串类型(1为计算数据,2为运算符)
输出 false或者true

3.3数据转换模块
3.3.1概述及流程图
在这里插入图片描述

图 3.3.1 数据转换模块流程图

接收输入模块或者算法模块传递来的数据。若接收到字符串,则将其转换为结构体;若接收到结构体,则将其转换为字符串。输出转换后的结构体或者字符串。
数据转换模块
功能 结构体和字符串之间的相互转换
输入 合法结构体/合法字符串
输出 字符串/结构体

3.3.2模块相关函数
(1)转结构体函数
在这里插入图片描述

图3.3.2(1)字符串转结构体流程图

函数接收字符串后,初始化bigNum结构体,首先判断第一个字符是否为符号,若为‘-’则记录符号位为负,为‘+’则记录符号位为正,转到下一个字符。若不为符号位则记录为正。(符号位确定)
判断字符是否为‘0’,若为‘0’则转向下一字符,若不为‘0’则继续执行,(过滤字符串前无意义0)
判断字符是否为‘.’,若为‘.’则转向下一字符,将‘.’后‘0’字符个数均过滤并记录偏移量后,将最终有效位字符串赋值。(处理0.开头数据,确定有效位和偏移量)
若不为‘.’则循环至‘.’,记录偏移量和有效位数。之后将‘.’后所有字符加入到有效位字符串并输出有效字符串好偏移量。若无‘.’,则直接输出有效字符串(处理整数和含整数部分小数确定有效位和偏移量)
最后若输出有效字符串为“”,则设置为“0”,输出最终结构体。

转结构体函数
函数 bigNum strToStruct(string num)
功能 将合法字符串转化为结构体
输入 合法字符串
输出 结构体bigNum

(2)转字符串函数
在这里插入图片描述

图3.3.2(2)结构体转字符串流程图

函数接收结构体后,判断结构体中有效位数长度是否超过20位,若未超出20位,则判断有效位是否为“0”,若是则直接输出“0”,否则判断偏移量是否小于有效字符串长度-1,若是则以小数形式生成字符串,若不是则以整数形式生成字符串。
若超出20位则截取有效字符串前20位字符,将‘.’插入到字符串第二位。以科学计数法方式生成字符串。
之后判断符号位是否为负,若是则在字符串首位添加‘-’,输出最终字符串。
图3.3.2(3)生成整数字符串流程图 图3.3.2(4)生成小数字符串流程图

图3.3.2(3)和图3.3.2(4)为 图3.3.2(2)拓展图,用于生成整数形式字符串和小数形式字符串。
整数形式应在字符串后补偏移量减字符串长度+1个‘0’。
小数形式分为小数点在有效字符串中和前,在有效字符串前时应向有效字符串前补偏移量的绝对值个‘0’,而在有效字符串中时,则在偏移量+1的下标位插入‘.’。

转字符串函数
函数 string structToString(bigNum num)
功能 将合法结构体转化为字符串
输入 合法结构体
输出 结果字符串

3.4算法模块
3.4.1概述及流程图
在这里插入图片描述

图3.4.1算法模块流程图

接收输入模块或者辅助处理模块传递而来的数据。判断运算符和计算数据正负并判断是否需要调用辅助模块中函数进行预处理。计算结束后,判断是否需要调用辅助模块中函数进行后处理,最后输出计算结果结构体。
数据转换模块
功能 对两个结构体进行加减乘除计算,输出计算结果结构体
输入 两个数据结构体和运算符
输出 结果结构体

3.4.2模块相关函数
(1)计算函数
在这里插入图片描述在这里插入图片描述

图3.4.2(1) 计算函数流程图 图3.4.2(2) 异号处理拓展图

计算函数获取需要计算的两个计算数据结构体及运算符,创建并初始化结果结构体,判断运算符。
若是‘+’或‘-’则继续判断两结构体的符号位。若同为正,则调用对应的结构体加减函数;若同为负,则调用对应的结构体加减函数后,进行符号位取反;若第一参数为负,则调换参数顺序调用与符号位相对的结构体加减函数。若运算符为‘-’时,将结果结构体中运算符取反;若第一参数为正,则调用与符号位相对的结构体加减函数;(图3.4.2(2)为图3.4.2(1)流程中异号处理的拓展)
若是‘*’或‘/’则调用对应的结构体乘除计算,获得结果后,判断两个计算数据结构体是否为异号,若为异号则符号位取负,若为同号,则符号位取正。
最终函数输出计算结果结构体。

计算函数
函数 bigNum calcul(bigNum num1,bigNum num2,string fuhao)
功能 根据运算符及结构体符号位,调用相应结构体计算函数,计算结果。
输入 两个计算数据结构体和运算符
输出 计算结果结构体

(2)结构体减法计算函数

在这里插入图片描述

图3.4.2(3)结构体减法计算流程图

结构体减法计算函数获取两结构体后,计算两结构结构小数位长度(字符串长度减去偏移量-1)。判断两结构体小数位数是否相等,若不相等则将小数位较少的结构体调用补位函数进行补0(小数位等长)。若相等则无操作。将两结构体有效位字符串作为参数调用字符串减法计算函数。得到结果后,判读字符串是否包含‘-’,若包含则将符号位设为负并移除‘-’。若不包含则无操作。之后将结果字符串赋值给结果结构体有效位字符串。最后将两计算结构体偏移量较大的值赋值给结果结构体偏移量并输出最终结果。

结构体减法计算函数
函数 bigNum structSub(bigNum num1,bigNum num2)
功能 对两结构体进行减法计算
输入 两个计算数据结构体
num1为被减数结构体
num2为减数结构体
输出 计算结果结构体

(3)结构体加法计算函数
在这里插入图片描述

图3.4.2(4)结构体加法计算流程图

结构体加法计算函数获取两结构体后,计算两结构结构小数位长度(字符串长度减去偏移量-1)。判断两结构体小数位数是否相等,若不相等则将小数位较少的结构体调用补位函数进行补0(小数位等长)。若相等则无操作。之后将两结构体有效位字符串作为参数调用字符串加法计算函数。得到结果后,将两计算结构体偏移量较大的值赋值给结果结构体偏移量。再然后判读字符串是否增长(结果字符串长度是否大于两),若增长则结果偏移量+1。若未增长则无操作。最后将结果字符串赋值给结果结构体有效位字符串并输出最终结果。

结构体加法计算函数
函数 bigNum structAdd(bigNum num1,bigNum num2)
功能 对两结构体进行加法计算
输入 两个计算数据结构体
输出 计算结果结构体

(4)结构体乘法计算函数
在这里插入图片描述

图3.4.2(5)结构体乘法计算流程图

结构体减法计算函数获取两结构体后,计算两结构结构小数位长度(字符串长度减去偏移量-1)。判断两结构体小数位数是否相等,若不相等则将小数位较少的结构体调用补位函数进行补0(小数位等长)。若相等则无操作。之后将两结构体有效位字符串作为参数调用字符串加法计算函数。得到结果后,将两计算结构体偏移量较大的值赋值给结果结构体偏移量。再然后判断结果字符串是否与两计算结构体的有效位字符串长度之和相等,若相等则结果偏移量+1。若不相等则无操作。最后将结果字符串赋值给结果结构体有效位字符串并输出最终结果。

结构体乘法计算函数
函数 bigNum structMul(bigNum num1,bigNum num2)
功能 对两结构体进行乘法计算
输入 两个计算数据结构体
输出 计算结果结构体

(5)结构体除法计算函数
在这里插入图片描述

图3.4.2(6)结构体除法计算流程图

结构体减法计算函数获取两结构体后,比较两结构体有效位长度是否相等。若不相等则对较短的结构体调用补位函数进行补位。若相等则无操作。之后将两结构体有效位字符串作为参数调用字符串除法计算函数。得到结果后,将结果字符串赋值给结果结构体有效位字符串,然后将两结构体偏移量相减并赋值给结果结构体偏移量,最后输出结果结构体。
结构体除法计算函数
函数 bigNum structDiv(bigNum num1,bigNum num2)
功能 对两结构体进行除法计算
输入 两个计算数据结构体
num1为被除数结构体
num2为除数结构体
输出 计算结果结构体

(6)字符串减法计算函数
string sub(string num1, string num2)
{
string res = “”;
int borrow = 0;
int i = num1.size() - 1, j = num2.size() - 1;
while (i >= 0 || j >= 0) {
int x = i >= 0 ? num1[i] - ‘0’ : 0;
int y = j >= 0 ? num2[j] - ‘0’ : 0;
int z = (x - borrow - y + 10) % 10;
res += ‘0’ + z;
borrow = x - borrow - y < 0 ? 1 : 0;
i–, j–;
}
reverse(res.begin(), res.end());
//删除前导0。循环条件是res.size()-1是为防止"0000"的情况
int pos;
for (pos = 0; pos < res.size() - 1; pos++) {
if (res[pos] != ‘0’) break;
}
//cout <<“减法:”<< res.substr(pos) << endl;
return res.substr(pos);
}
string strSub(string num1, string num2)
{
string res;
if (isLess(num1, num2)) {
res = sub(num2, num1);
res.insert(0, “-”);
}
else res = sub(num1, num2);
return res;
}
字符串减法计算函数
函数 string strSub(string num1, string num2)
功能 对两字符串进行减法计算
输入 两个计算数据字符串
num1为被减数字符串
num2为减数字符串
输出 计算结果字符串

(7)字符串加法计算函数
参考https://leetcode-cn.com/problems/add-strings/solution/
string strAdd(string num1, string num2) {
if (num1 == “” || num1 == “0”) return num2;
if ( num2 == “” || num2 == “0”) return num1;

int l1 = num1.length() - 1;
int l2 = num1.length() - 1;
int carry = 0;
string ans = "";
while (l1 >= 0 || l2 >= 0) {
	int x = (l1 >= 0) ? num1[l1] : '0';    // 注意是'0',不是0
	int y = (l2 >= 0) ?  num2[l2] : '0';    // 注意是'0',不是0
	int s = (x - '0') + (y - '0') + carry;
	ans = to_string(s % 10) + ans;
	carry = s / 10;
	if (l1 >= 0) l1--;
	if (l2 >= 0) l2--;
}
if (carry != 0) ans = "1" + ans;
return ans;

}
字符串加法计算函数
函数 string strAdd(string num1, string num2)
功能 对两字符串进行加法计算
输入 两个计算数据字符串
输出 计算结果字符串

(8)字符串乘法计算函数
参考https://www.cnblogs.com/flix/p/12687561.html
string multiply(string num1, string num2) {
if(num1==“0” || num2==“0”) return “0”;
if(num1==“1”) return num2; if(num2==“1”) return num1;
int res[num1.length()+num2.length()];
memset(res, 0, sizeof(res));
for(int i=num1.length()-1; i>=0; i–){
int n1 = num1[i]-‘0’;
for(int j=num2.length()-1; j>=0; j–){
int n2 = num2[j]-‘0’;
int s = res[i+j+1]+n1*n2;
res[i+j+1] = s%10; // 低位
res[i+j] += s/10; // 高位
}
}
string ans = “”;
for(int i=0; i<num1.length()+num2.length(); i++){
if(i==0 && res[i]==0) continue;
ans += to_string(res[i]);
}
return ans;
}
字符串乘法计算函数
函数 string multiply(string num1, string num2)
功能 对两字符串进行乘法计算
输入 两个计算数据字符串
输出 计算结果字符串

(9)字符串除法计算函数
string strDiv(string num1, string num2)
{
int alen = num1.size();
int blen = num2.size();
char resault[51]{0};
for (int i = 0; i < 50; i++)
{
int z = 0;
while (1)
{
string res = strSub(num1, num2);
if (res[0] == ‘-’)
{

			break;
		}
		else if (res == "0")
		{
			z++;
			resault[i] = z + '0';
			return resault;
		}
		else
		{
			num1 = res;
			z++;
		}
	}
	num1.append("0");
	resault[i] = z + '0';
}
return resault;

}
字符串除法计算函数
函数 string strDiv(string num1, string num2)
功能 对两字符串进行除法计算
输入 两个计算数据字符串
num1为被除数字符串
num2为除数字符串
输出 计算结果字符串

3.5辅助处理模块
3.5.1概述及流程图

在这里插入图片描述

图3.5.1 辅助处理模块流程图

接收算法模块传来的数据结构体。调用相应辅助函数。处理结束后,返回结果结构体。
辅助处理模块
功能 将算法模块传入的数据,调用相关进行对应的辅助处理
并返回结果结构体
输入 数据结构体及相关参数
输出 结果结构体

3.5.2模块相关函数
(1)补位函数
在这里插入图片描述

图3.5.2(1)补位流程图

补位函数接收到结构体及补零个数后,将结构体中有效位字符串尾部补相应个数的‘0’,最后输出相应结果结构体。
补位函数
函数 bigNum cover (bigNum num1,int zeronum)
功能 将结构体有效位字符串后补0
输入 数据结构体和需要补零的个数
输出 结果结构体
(2)规范函数
在这里插入图片描述

图3.5.2(2)补位流程图

补位函数接收到结构体后,判断有效位字符串开头是否为‘0’,若为‘0’则移除字符串首位‘0’,且偏移量-1,重新判断;直到有效位字符串开头不为‘0’,判断有效字符串是否为空,若为空则设有效字符串为“0”输出结果结构体。
规范函数
函数 bigNum norm (bigNum num1)
功能 将结构体规范为科学计数法表示结构体
输入 数据结构体
输出 结果结构体

3.6输出模块
3.6.1概述及流程图
在这里插入图片描述

图3.6.1输出模块流程图

将获取的字符串显示在界面上。

输出模块
功能 显示字符串
输入 计算结果字符串
输出 显示字符串在界面
3.6.2模块相关函数
(1)显示函数
在这里插入图片描述

将字符串显示在界面上。
规范函数

函数 string display (string num1)
功能 显示字符串
输入 计算结果字符串
输出 显示字符串在界面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值