已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
数学表达式的计算,在一些资料及网上查阅的资料,表达式的各项是一个一个输入的,不能像 Excel 函数那样一次性输入整个表达式,显得很不自然。 一次性输入整个表达式,然后计算这个表达式的值,重点是正确地从整个表达式中正确地分离出每一项。 以下是程序,程序中解释详细,就不多叙述。/ 程序在 Visual Studio 2013 C+ 中测试通过/* 说明:为支持输入 等习以为常的数学运算符号而计算机不支持的运算符号,程序中字符、字符串一律使用双字节字符类型:wchar_t */ MathExpression.h 声明处理、计算表达式的函数/#pragma once/用于保存分离出的表达式项struct ExpressionItemdouble Operand;/操作数wchar_t OperateChar;/操作符,如果为 0,为操作数short Isp;/操作符的栈内优先级short Icp;/操作符的栈外优先级short Preserve;/暂时无用,目的是实现 4 字节(8 字节)对齐;/文本预处理。/支持: x X 中文括号 空格bool StringPreprocess(wchar_t *pwch);/解析表达式/解析结果通过 pOut 输出,pOut 内存由调用者负责/返回:解析出数据的数目,返回 0,表达式不符合要求int AnalyzeExpression(const wchar_t *pwch, ExpressionItem *pOut);/将中缀表达式转换成后缀表达式int InfixToPostfix(ExpressionItem *pIn, ExpressionItem *pOut, int ExpressionItemsCount);/计算后缀表达式的值double CalculateExpression(ExpressionItem *pIn, int count);/ MathExpression.cpp :声明计算表达式的函数。/#include stdafx.h#include math.h#includeusing namespace std;#include MathExpression.h/检查字符是否合法。完成一些非标准符号的转换/返回值: true 成功,false 存在非法字符。static bool CheckChar(wchar_t &wch)switch (wch)case _T(() :wch = (;/将中文的括号换成 ASCII 的括号break;case _T()):wch = );break;case E:wch = e;/将浮点数的阶码符号 E 一律换成小写的 ebreak;case _T(): case x: case X:wch = *;/将数学的 (包括字母:x X) 改成标准的 *break;case _T():wch = /;break;/检查字符的合法性if (wch = 0 & wch = 9)/是数字return true;else if (wch = | wch = .)return true;/合法的操作符else if(wch = + | wch = - | wch = * | wch = / | wch = ( | wch = ) | wch = | wch = %)return true;/合法的操作符else if (wch = e | wch = 0)return true;/结束符,合法/挑选剩余的是非法字符return false;/文本预处理。/去除空格,将中文的括号换成 ASCII 的括号,将浮点数的阶码符号 E 一律换成小写的 e 。/将数学的 (包括字母:x X) 改成标准的 *、 改成标准的 /。/返回值: true 成功,false 存在非法字符。bool StringPreprocess(wchar_t *pwch)int i = 0, j = 0; /循环计数变量wchar_t tmp;int ParenthesesCount = 0;/用于判断括号是否匹配for (;) /使用 for 循环效率较高/去除空格tmp = pwchj; /使用临时变量,提高效率if (!CheckChar(tmp) return false;/检查字符是否合法。if (tmp = 0)/ 扫描完毕pwchi = 0;/写入字符串结束的符号break;elseif (tmp = )/是空格,不予保留j+;/继续扫描下一个else/不是空格,保留数据。方式是前移pwchi = tmp;/计数 (、)if (tmp = () ParenthesesCount+;else if (tmp = ) ParenthesesCount-;i+; j+;/继续扫描下一个if (ParenthesesCount = 0)return true;/括号匹配elsereturn false;/括号不匹配/提取数型数据。static double PickupValue(const wchar_t *pwch, int &pos)double sign = 1.0;/用于记录符号double esign = 1.0;/用于记录指数符号wchar_t curwch;double mantissa = 0.0, mantissa_decimal = 0.0;double exponent = 0.0, exponent_decimal = 0.0;double x;curwch = pwchpos;if (curwch = -)/是符号 -sign = -1.0;/记录下来pos+;/指向下一个字符else if (curwch = +)/是符号 +sign = 1.0;/记录下来pos+;/指向下一个字符/将表示尾数的字符串转换成数for (;)/运行效率比 while(1)高/计算尾数的整数部分curwch = pwchpos;/取当前字符。if (curwch 9) break;/不是数字mantissa = mantissa * 10.0 + (curwch - 0);/计算尾数。pos+;/指向下一个字符if (curwch = .)/计算尾数的小数部分pos+;/指向下一个字符x = 1.0;/用于累计乘以 10 的次数for (;)/运行效率比 while(1)高/计算尾数的小数部分curwch = pwchpos;/取当前字符。if (curwch 9) break;/不是数字mantissa_decimal = mantissa_decimal * 10.0 + (curwch - 0);/计算尾数x *= 10.0;/用于累计乘以 10 的次数pos+;/指向下一个字符mantissa_decimal /= x;mantissa += mantissa_decimal;/尾数 = 整数部分 + 小数部分mantissa *= sign;/将符号加上if (curwch = e)/接下来的是阶码pos+;/指向下一个字符curwch = pwchpos;/取当前字符。if (curwch = -)/是符号 -esign = -1.0;/记录下来pos+;/指向下一个字符else if (curwch = +)/是符号 +esign = 1.0;/记录下来pos+;/指向下一个字符for (;)/运行效率比 while(1)高/将表示阶码的字符串转换成数curwch = pwchpos;/取当前字符。if (curwch 9) break;/不是数字exponent = exponent * 10.0 + (curwch - 0);/计算阶码pos+;/指向下一个字符if (curwch = .)/计算指数的小数部分pos+;/指向下一个字符x = 1.0;/用于累计乘以 10 的次数for (;)/运行效率比 while(1)高/计算尾数的小数部分curwch = pwchpos;/取当前字符。if (curwch 9) break;/不是数字exponent_decimal = exponent_decimal * 10.0 + (curwch - 0);/计算尾数x *= 10.0;/用于累计乘以 10 的次数pos+;/指向下一个字符exponent_decimal /= x;exponent += exponent_decimal;/阶码 = 整数部分 + 小数部分exponent *= esign;/将符号加上return mantissa * pow(10, exponent);/返回结果:浮点数数 = 尾数 * 10阶码/判断当前是否是操作数。是:返回 1,不是:返回 0,非法表达式:-1static int IsOperand(const wchar_t *pwch, int pos)wchar_t curwch = pwchpos, tmpwch;bool b1, b2;if (curwch = 0 & curwch = 0 & pwchpos + 1 = 0 & tmpwch = 0 & tmpwch = 0 & pwchpos + 1 = 0 & tmpwch = 9) | tmpwch = ) | tmpwch = .)return true;/前面不是数字return false;/表达式有效性检测static bool ExpressionValid(const ExpressionItem *pEi, int count)/有效的检测:项数必为奇数,一定是一操作数开始,不计括号,操作数与操作符交替出现。if (count 3) return false;/表达式最少有 3 项wchar_t wch = pEi0.OperateChar;if (wch != 0) return false;/表达式一定是一操作数开始bool is_operand = true;int i;for (i = 0; i count; i+)/表达式的操作数与操作符交替出现wchar_t wch = pEii.OperateChar;if (wch = ( | wch = ) continue;/不计括号if (is_operand) /当前应该是操作数。操作数:wch = 0if (wch != 0) return false;else/当前应该是操作符。操作符:wch != 0if (wch = 0) return false;is_operand = !is_operand;return true;/通过重重检测,表达式有效/解析表达式。int AnalyzeExpression(const wchar_t *pwch, ExpressionItem *pOut)wchar_t curwch;int pos = 0, k = 0;int a;for (;)curwch = pwchpos;if (curwch = 0) break;/结束循环/判断是操作数还是操作符a = IsOperand(pwch, pos);if (a = -1) return 0;/非法表达式if (a = 1)/是操作数pOutk.Operand = PickupValue(pwch, pos);pOutk.OperateChar = 0;pOutk.Isp = 0;pOutk.Icp = 0;k+;/准备输出下一个解析结果else/是操作符if (SignBrackets(pwch, pos)/符号是修饰括号内结果的符号。/插入一个操作数:0pOutk.Operand = 0;pOutk.OperateChar = 0;pOutk.Isp = 0;pOutk.Icp = 0;k+;/准备输出下一个解析结果/输出这个特殊的高优先级的双目减(加)法pOutk.Operand = 0;pOutk.OperateChar = curwch;pOutk.Isp = 9;pOutk.Icp = 8;pos+;/指向下一个字符k+;/准备输出下一个解析结果else/符号是修饰括号内结果的符号pOutk.Operand = 0.0;pOutk.OperateChar = curwch;JdugePriority(pOutk);/确定优先级pos+;/指向下一个字符k+;/准备输出下一个解析结果if (!ExpressionValid(pOut, k) return 0;/表达式有效性检测:无效/在表达式最后放一个“#”pOutk.Operand = 0.0;pOutk.OperateChar = #;pOutk.Isp = 0;pOutk.Icp = 0;return k + 1;/将中缀表达式转换成后缀表达式/转换结果通过 pOut 输出,pOut 内存分配由调用者负责。int InfixToPostfix(ExpressionItem *pIn, ExpressionItem *pOut, int ExpressionItemsCount)stack s;ExpressionItem ch, op;int i, j;ch.Operand = 0.0;ch.OperateChar = #;ch.Isp = 0;ch.Icp = 0;s.push(ch);/栈底放一个#i = 0; ch = pIni;/读入一个字符(取表达式第一个元素)j = 0;while (!s.empty() & i = ExpressionItemsCount)return 0; ch = pIni;/读下一个字符(取表达式下一个元素)else/是操作符if (ch.Icp s.top().Isp)/新输入(当前)的操作符优先级高s.push(ch);/进栈i+;if (i = ExpressionItemsCount)return 0; ch = pIni;/读下一个字符(取表达式下一个元素)else if (ch.Icp = ExpressionItemsCount)return 0;ch = pIni;/读下一个字符(取表达式下一个元素)if (s.empty()return j;/表达式如果正确的话,运行到这里栈一定是空elsereturn 0;/从栈中取出 2 个操作数static bool Get2Operands(stack& s, double& left, double& right)if (s.empty() return false;/栈空,操作数不存在right = s.top(); s.pop();/取右操作数if (s.empty() return false;/栈空,操作数不存在left = s.top(); s.pop();/取左操作数return true;/取两个操作数,形成运算指令并计算static bool DoOperator(stack& s, wchar_t op)double left, right;if (!Get2Operands(s, left, right) return false;/取操作数失败/取操作数成功switch (op)case +:/加s.push(left + right);break;case -:/减s.push(left - right);break;case *:/乘s.push(left * right);break;case /:/除s.push(left / right);break;case %:/取余s.push(double)(long)left % (long)right);break;case :/指数s.push(pow(left, right);break;default:return false;break;return true;/计算后缀表达式的值double CalculateExpression(ExpressionItem *pIn, int count)long long x = 0x7FFFFFFFFFFFFFFF; double* px = (double*)&x;if (count 3) return *px;/表达式至少有 3 项int i;ExpressionItem ei;stack s;for (i = 0; i count; i+)ei = pIni;if (ei.OperateChar = 0)/是操作数,入栈s.push(ei.Operand);else/是操作符,执行计算if(!DoOperator(s, ei.OperateChar) return *px;/返回错误return s.top();/ Test.cpp : 定义控制台应用程序的入口点。/ 测试程
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 绿城集团招聘测试题库
- 九年级下册历史教案人教版
- 九年义务教育物理中考试题分类(内能)
- 加强飞行器电池回收促进绿色循环经济-某地区实践探索
- 加强跨区域协作以提高长三角涉企执法互认机制的有效性
- 统编五年级上册《习作:“漫画”老师》课件
- 拟人句测试题及答案解析
- 重庆市大渡口区2027届九年级数学第一学期期末质量跟踪监视模拟试题含解析
- 2027届广东省东莞市常平嘉盛实验学校数学八年级第一学期期末调研模拟试题含解析
- 睡眠管理家长最容易忽略的事
- DB42T 1319-2021 绿色建筑设计与工程验收标准
- 甲乳外科泌尿外科护理
- 医院与护理公司协议合同
- GB/T 18936-2025禽流感诊断技术
- 新一代数据中心建设投资协议
- 宁夏林利煤炭有限公司煤矿三号井“9·27”重大瓦斯爆炸事故调查报告
- 职称评定专业技术报告
- JB-T 14509-2023 反渗透海水淡化设备技术规范
- 子宫内膜癌的早期诊断与治疗之提高治愈率
- GB/T 2820.1-2022往复式内燃机驱动的交流发电机组第1部分:用途、定额和性能
- 密炼机说明书z
评论
0/150
提交评论