混和运算

用计算器比较麻烦,因为它不按计算顺序来,需要按很多次(加之平时用得少,又掺进来负数,按上十来次就按错了)。出于统计方便,写了个程序专门算数。

效果如下(格式不作要求,只要输对就行):

主要代码:

/*///////////////////////////////////////

带括号的四则运算:

-------------------------------------
1、中序转为后序表达式
顺序读取,对不同对象按不同情况处理:

1)运算数:直接输出
2)左括号:压入堆栈
3)右括号:将栈的运算符弹出并输出,直到遇到左括号(弹出,不输出)
4)运算符:
若优先级大于栈顶运算符,则把它压栈
若优先级小于等于栈顶运算符,将栈顶运算符弹出并输出,再比较新的栈顶运算符,
直到该运算符优先级大于栈顶运算符为止,然后将该运算符压栈
5)若所有对象处理完毕,则把堆栈中残留的运算符一并输出

--------------------------------------
2、计算后序表达式
每遇到运算符则对它之前的两个数计算

--------------------------------------
程序支持形如 -0.3 + 4 * (-1.5 + -6.4 / -2) * -4 形式的算式

////////////////////////////////////////*/
#include "LinkedStack.h"
#include <string>
#include <sstream>
#include <iostream>
using namespace std;

string Calculate(char oper, double a, double b)
{
    switch(oper)
    {
    case '+':a += b; break;
    case '-':a -= b; break;
    case '*':a *= b; break;
    case '/':
         if(b != 0)
             a /= b;
         else
             throw BadInput();
    }
    stringstream stream;
    stream << a;
    string str;
    stream >> str;
    return str;
}

// 删除字符串中空格
void trim(string &str, string::size_type pos = 0)
{
    static const string delim = " \t"; //删除空格或者tab字符
    pos = str.find_first_of(delim, pos);

    if(pos == string::npos)
        return;

    trim(str.erase(pos, 1));
}

// 从某处起略过数字添加右括号
void AddRight(string& line, int i)
{
    int len = line.length();
    ++i;
    while(i < len && (line[i] == '0' || line[i] == '1' ||
        line[i] == '2' || line[i] == '3' || line[i] == '4' ||
        line[i] == '5' || line[i] == '6' || line[i] == '7' ||
        line[i] == '8' || line[i] == '9' || line[i] == '.'))
        ++i;
    line.insert(i, ")");
}

// 处理负数和正号
string&  HandleExp(string& line)
{
    trim(line);

    if(line[0] == '-' || line[0] == '+')
    {
        AddRight(line, 0);  // 先补右括号
        line = "(0" + line; // 再补左括号
    }        

    // 需用 line.length(),因为长度不断在变化
    for(unsigned i = 1; i < line.length(); ++i)
    {
        if(( line[i] == '-' || line[i] == '+') &&
           ( line[i - 1] == '+' || line[i - 1] == '-' ||
             line[i - 1] == '*' || line[i - 1] == '/' ||
             line[i - 1] == '(' ))
        {
            AddRight(line, i); // 先补右括号
            line = line.insert(i, "(0");
        }
    }
    return line;
}

// 处理表达式,并将中序转后序表达式,并进行计算
string InToPost(string& line)
{
    line = HandleExp(line);

    LinkedStack<string>num;
    LinkedStack<char>symb;

    char op;
    double a,b;
    int size = line.length(), i;
    string item("");

    for(i = 0; i < size; ++i)
    {
        if(line[i] == '(')
        {
            symb.Add('(');
            continue;
        }
        if(line[i] == '*' || line[i] == '/')
        {
            if(item != "")
            {
                num.Add(item);
                item = "";
            }

            if( !symb.IsEmpty() && symb.Top() != '('
                &&(symb.Top() == '*' || symb.Top() == '/'))
            {
                symb.Delete(op);
                num.Delete(item);
                b = strtod(item.c_str(), NULL);
                num.Delete(item);
                a = strtod(item.c_str(), NULL);
                num.Add( Calculate(op, a, b) );
                item = "";
            }
            symb.Add(line[i]);
            continue;
        }

        if(line[i] == '+' || line[i] == '-')
        {
            if(item != "")
            {
                num.Add(item);
                item = "";
            }

            if(!symb.IsEmpty() && symb.Top() != '(' )
            {
                symb.Delete(op);
                num.Delete(item);
                b = strtod(item.c_str(), NULL);
                num.Delete(item);
                a = strtod(item.c_str(), NULL);
                num.Add(Calculate(op, a, b));
                item = "";
            }
            symb.Add(line[i]);
            continue;
        }
        if(line[i] == ')')
        {
            if(item != "")
            {
                num.Add(item);
                item = "";
            }
            while(!symb.IsEmpty() && symb.Top() != '(')
            {
                symb.Delete(op);
                num.Delete(item);
                b = strtod(item.c_str(), NULL);
                num.Delete(item);
                a = strtod(item.c_str(), NULL);
                num.Add(Calculate(op, a, b));
            }
            symb.Delete(op); // 删除 (
            item = "";
            continue;
        }
        else
        {
            item += line[i];
        }
    }

    // 最后一个数字
    if(item != "")
    {
        num.Add(item);
        item = "";
    }

    while(!symb.IsEmpty())
    {
        symb.Delete(op);
        num.Delete(item);
        b = strtod(item.c_str(), NULL);
        num.Delete(item);
        a = strtod(item.c_str(), NULL);
        num.Add(Calculate(op, a, b));
    }

    return num.Top();
}
时间: 2024-10-08 16:46:28

混和运算的相关文章

用BlendFunc实现舞台灯光和刮刮卡效果

[转]http://code.lovemiao.com/?p=136#more-136 之前写过一篇<不规则形状按钮的点击判定>,利用了CCRenderTexture创建一块画布,可以在上面随意作画,这次,美术同学又本着把程序员折腾到底的态度,提出了又一奇葩需求,由于原需求设计商业机密,这里仅举个同理的例子说明. 附带福利图一张: 神马?没看够?还想看看其他人?请看耐心完全文 要做到上面的效果,glBlendFunc是个很好的选择.glBlendFunc是一个设置图像叠加方式的函数,就是把一张

最全加密算法之对称加密和非对称加密

常见加密算法 : DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合: 3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高: RC2和 RC4:用变长密钥对大量数据进行加密,比 DES 快: IDEA(International Data Encryption Algorithm)国际数据加密算法:使用 128 位密钥提供非常强的安全性: RSA:由 RSA 公司发明,是一个支持变长密钥的公共

结对作业2——自动生成四则运算

软件结对作业三 1 选择题目 我们在刚开始上课的时候介绍过一个小学四则运算自动生成程序的例子,请实现它,要求: 能够自动生成四则运算练习题 可以定制题目数量 用户可以选择运算符 用户设置最大数(如十以内.百以内等) 用户选择是否有括号.是否有小数 用户选择输出方式(如输出到文件.打印机等) 最好能提供图形用户界面(根据自己能力选做,以完成上述功能为主) 二.单元测试 1 代码运行结果 (1)首先展示的是代码运行成功的界面: (2)以下为加减乘除四种不同运算方式下随机产生的题目: 注:其中用户可以

位运算之 C 与或非异或

位运算比较易混: 位运算之 C 与或非异或 与运算:& 两者都为1为1,否则为0 1&1=1,  1&0=0,  0&1=0,  0&0=0 或运算:| 两者都为0为0,否则为1 1|1 = 1,  1|0 = 1,  0|1 = 1, 0|0 = 0 非运算:~ 1取0,0取1 ~1 = 0, ~0 = 1 ~(10001) = 01110 异或运算:^ 两者相等为0,不等为1(易混淆) 1^1=0, 1^0=1, 0^1=1, 0^0=0 位移操作符:<&

java位运算

Java的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long.int.short.char和 byte,位运算符具体如下表: 运算符 说明 << 左移位,在低位处补0 >> 右移位,若为正数则高位补0,若为负数则高位补1 >>> 无符号右移位,无论正负都在高位补0 & 与(AND),对两个整型操作数中对应位执行布尔代数,两个位都为1时输出1,否则0. | 或(OR),对两个整型操作数中对应位执行布尔代数,两个位

Java 位运算

一,Java 位运算 1.表示方法: 在Java语言中,二进制数使用补码表示,最高位为符号位,正数的符号位为0,负数为1.补码的表示需要满足如下要求. (l)正数的最高位为0,其余各位代表数值本身(二进制数). (2)对于负数,通过对该数绝对值的补码按位取反,再对整个数加1. 2.位运算符 位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算.位运算符可以分为逻辑运算符(包括~.&.|和^)及移位运算符(包括>>.<<和>>>). 1)左

深入理解计算机系统(2.2)---布尔代数以及C语言上的位运算

本文转载地址:http://www.cnblogs.com/zuoxiaolong/p/computer6.html 布尔代数上的位运算 布尔代数是一个数学知识体系,它在0和1的二进制值上演化而来的. 我们不需要去彻底的了解这个知识体系,但是里面定义了几种二进制的运算,却是我们在平时的编程过程当中也会遇到的.这四种运算分别是或.与.非和异或.下图展示了在布尔代数的知识体系中,对这四种运算的定义. 从左至右依次是非.与.或以及异或.这个图阐述的是针对一位二进制的运算结果,我们可以将其扩大到N位二进

Objective-C 与 Swift 混编之路

本文摘自: http://blog.csdn.net/mmoaay/article/details/48422309 本文内容基于 Xcode 6.4 和 Swift 1.2 重要资料 Using Swift with Cocoa and Objective-C 官方文档 为什么要混编? 语言发展趋势(TIOBE),Swift 排行持续上升, OC 排行呈重力下降 项目正常迭代需要  很多第三方库仍然使用 OC 实现 项目中原来已经用 OC 实现的模块如果使用 Swift 重写,代价稍大 我们需

润乾集算报表非常规统计之跨行组运算

报表开发中,经常会碰到一些需要进行非常规统计的报表,固定分组.可重复分组.组内排序,还包括跨行组计算的报表,甚至有些报表本身无数据来源.以及需要对数据源再计算.这些报表本身具备一定的特殊性,使用常规方法往往难于实现. 集算报表完成这类特殊统计报表则非常简单,这里通过一个需要完成跨行组计算的报表为例,说明使用集算报表的实现过程. 报表说明 根据订单表和指定年份(参数)按月统计订单金额,以及与上一订单月金额比,与去年同月金额比.报表样式如下: 这里应该注意的是比去年同期是指与去年同月份的比值,无对应