1 Star 0 Fork 4

skylens / MFC实现浮点计算器

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
0BSD

简介

VS2019编写的计算器,支持括号和小数运算和进制转换 当进制发生转换时,如果表达式框内有表达式,会计算后转化,支持小数转换,如果表达式有误,将直接清空。

界面

输入图片说明

实现方法

表达式框添加控制变量CString类型的m_sEquation,除了求值运算其他按键都可以认为是对字符串的操作

下面重点介绍值的运算,为此写了一个MyCalculator类,它有两个成员函数:

bool MyCalculator::Calc(CString Equation, CString &ans, int radix) 传入表达式Equation,和进制radix(默认为十进制),将计算结果存入ans中 当表达式有错误时,如"(1+1++1)","(1+6",函数返回值FALSE,否则返回TRUE 被除数为0时,ans赋值为"除0异常"

为了获取小数,需要下面的GetNum函数,传入表达式Eq,起始位置i,进制radix,注意这个函数不可以直接处理负数

  • 对于整数部分,和普通整数变换一样$x=x*10+Eq[i]-'0'$,但是现在不一定是十进制,换成$*radi$x就可以;
  • 判断是否有小数点
  • 如果有,小数部分第i位要乘上$1/radix$的i次方
double GetNum(CString& Eq, int& i, int radix)
{
	double x = 0;
	while (i<Eq.GetLength() && IsNum(Eq[i]))
	{
		x = x * radix + Eq[i] - '0';
		i++;
	}
	double rad = 1.0 / radix;
	if (i < Eq.GetLength() && Eq[i] == '.') 
	{
		i++;
		while (i < Eq.GetLength() && IsNum(Eq[i]))
		{
			x = x + (Eq[i] - '0') * rad;
			rad = rad / radix;
			i++;
		}
	}
	return x;
}

计算表达式的整体过程是通过表达式栈实现 num数字表达式 opt操作符表达式 因为有负数,已经要判断"2++3"之类错误,不方便直接判断某一位到底是数还是操作符,但是所有表达式都有一个特点:除了括号数字后面一定是操作符,操作符后面一定是数字,左括号左是操作符右是数字,右括号左是数字又是操作符,所以可以写以下循环

$while$ 表达式未处理完:

  • 判断左括号,可能没有
  • 得到数字(先判断符号再GetNum),入栈
  • 判断右括号,如果有,出栈至左括号
  • 得到操作符,把操作符栈顶优先级不比它低的出栈,自己入栈

最后所有操作符出栈

这里出栈是指取出操作符和两个操作数,运算后结果数入栈这一整个过程

bool MyCalculator::Calc(CString Equation, CString &ans, int radix) 
{
	double num[MAXNUM];
	int ntop = 0;
	char opt[MAXOPT];
	int otop = 0;
	int Len = Equation.GetLength();

	for (int i = 0 ; i < Len; )
	{
		if (Equation[i] == '(')
		{
			opt[++otop] = Equation[i++];
			if (i >= Len) return FALSE;
		}

		bool flag = false;
		if (Equation[i] == '-')
		{
			flag = true;
			i++;
			if (i >= Len) return FALSE;
		}
		if (!IsNum(Equation[i]))
			return FALSE;
		num[++ntop] = GetNum(Equation, i, radix) * (flag ? -1 : 1);
		if (i >= Len) break;

		if (Equation[i] == ')')
		{
			while (otop > 0 && opt[otop] != '(') 
			{
				INT cas = GetOutSta(num, ntop, opt, otop);
				if (cas == -1) return FALSE;
				if (cas == 0) {
					ans = _T("除0异常");
					return TRUE;
				}
			}
			if (otop == 0) return FALSE;
			otop--;
			i++;
			if (i >= Len) break;
		}

		if (!IsOpt(Equation[i]))
			return FALSE;
		while (otop > 0 && opt[otop]!='(' && !Greater(Equation[i],opt[otop])) 
		{
			INT cas = GetOutSta(num, ntop, opt, otop);
			if (cas == -1) return FALSE;
			if (cas == 0) {
				ans = _T("除0异常");
				return TRUE;
			}
		}
		opt[++otop] = Equation[i++];
		if (i >= Len) return FALSE;
	}
	//return 0;
	while (otop) {
		INT cas = GetOutSta(num,ntop,opt,otop);
		if (cas == -1) return FALSE;
		if (cas == 0) {
			ans = _T("除0异常");
			return TRUE;
		}
	}
	if (ntop != 1) return FALSE;
	ans.Format(_T("%g"), num[ntop]);
	if (radix != 10) {
		ConvertRad(ans, 10, radix);
	}
	return TRUE;
}

bool MyCalculator::ConvertRad(CString& Num, int radixFrom, int radixTo) 传入原数字Num,转换前的进制radixFrom,转换后的进制radixTo,转换失败时(Num不是数字)返回FALSE

首先用GeNum转换为double型dtmp

  • 如果是负数dtmp=-dtmp,ans加‘-’
  • 整数部分用自带的_itoa_s转换
  • 小数部分不断乘radixTo,顺序取整数位,默认最多转成8位小数
bool MyCalculator::ConvertRad(CString& Num, int radixFrom, int radixTo)
{
	int Len = Num.GetLength();
	int j = 0;
	bool flag = false;
	if (Num[j] == '-') {
		j++;
		flag = true;
	}
	double dtmp = GetNum(Num,j,radixFrom);
	if (j != Len) return FALSE;
	Num = "";
	if (flag) {
		Num = "-";
	}
	int itmp = (int)dtmp;
	char str[100];
	_itoa_s(itmp, str, 100, radixTo);
	Num += (CString)str;
	dtmp -= itmp;
	int dotLen = 0;
	if (dtmp > 1e-7) {
		Num += ".";
		while (dtmp > 1e-7 && dotLen <= 8) {
			dtmp *= radixTo;
			Num += static_cast<char>('0'+(int)dtmp);
			dtmp = dtmp - (int)dtmp;
		}
	}
	return TRUE;
}
Copyright (c) 2020 rewine Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

简介

VS2019编写的计算器,支持浮点运算和进制转换 展开 收起
C++
0BSD
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
C++
1
https://gitee.com/skylens/mfc_implementation_calculator.git
git@gitee.com:skylens/mfc_implementation_calculator.git
skylens
mfc_implementation_calculator
MFC实现浮点计算器
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891