noi.openjudge 3340:RPN Calculator

本文介绍了一种基于逆波兰表达式(RPN)的简单计算器的设计与实现,该计算器能够处理加、减、乘、除及幂运算,支持双精度浮点数计算,并具备记忆功能,每次计算后会更新内存中的最小值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://noi.openjudge.cn/ch0303/3340/

描述

Reverse Polish notation (or just RPN) by analogy with the related Polish notation, a prefix notation introduced in 1920 by the Polish mathematician Jan Łukasiewicz, is a mathematical notation wherein every operator follows all of its operands. It is also known as Postfix notation.

In Reverse Polish notation the operators follow their operands; for instance, to add three and four one would write “3 4 +” rather than “3 + 4”. If there are multiple operations, the operator is given immediately after its second operand; so the expression written “3 − 4 + 5” in conventional infix notation would be written “3 4 − 5 +” in RPN: first subtract 4 from 3, then add 5 to that. An advantage of RPN is that it obviates the need for parentheses that are required by infix. While “3 − 4 * 5” can also be written “3 − (4 * 5)”, that means something quite different from “(3 − 4) * 5”, and only the parentheses disambiguate the two meanings. In postfix, the former would be written “3 4 5 * −”, which unambiguously means “3 (4 5 *) −”.

You were asked to design a simple RPN calculator, which will support the “+”, “-“, “*”, “/”(the absolute value of the divisor will not less then 10^-9) and “^”(power operator, if the base number b<=0, the exponential e must be a positive integer not greater than 10^9) operators. You can assume all the numbers during the calculation can fit into a double-precision floating point number.

In addition, our calculator has some memory. Each time we calculate an expression, the smallest number in the memory will be erased, and replace it with the value of the expression.

输入

The first line contains an integer n, which is the memory size of our calculator.

From the second line, we will give n numbers, which is the initial value of the memory. each line except last will have 10 numbers.

And then each line has a valid RPN expression we previously described, end with “=”, which is the command for calculation. Each term will no longer than 20 characters.

输出

For each expression, output the value of it in a line.
And then output an empty line to separate the two parts.
At last, output the all the numbers in memory, in increasing order, 10 numbers per line.

Each number should be formatted in scientific notation with 6 digits after decimal point and 2 digits of exponential, such like “%e” format string of printf() function in C. The numbers in a line should be separated by a space.

样例输入

4
1e6 1e-6 0.001 1000
1 2 + 3 4 + * =
1 0.1 / 8 ^ =

样例输出

2.100000e+01
1.000000e+08

2.100000e+01 1.000000e+03 1.000000e+06 1.000000e+08

提示

Huge input, scanf() is recommended

%e格式输出在windows环境下指数部分为3位,在系统的测试环境下为2位。

代码

/*
后缀表达式的计算 
用一个栈来存储数字,从左向左右遍历表达式 
遇到数字就压栈 
遇到操作符就弹出栈中的两个数字计算并压栈 
最后栈中剩余的数字是我们要的结果  
*/
#include<iostream>
#include<iomanip>
#include<stdio.h>
#include<math.h>
#include<stack>
#include<queue>
using namespace std;

void cal(string param, stack<double> &num)
{
    double num1=num.top();num.pop();
    double num2=num.top();num.pop();
    if(param=="+")num.push(num2+num1);
    if(param=="-")num.push(num2-num1);
    if(param=="*")num.push(num2*num1);
    if(param=="/")num.push(num2/num1);
    if(param=="^")num.push(pow(num2,num1));
}

void bolan(string &param, stack<double> &num)
{
    if(param!="+" && param!="*" && param!="-" && param!="/" && param!="^")// 遇到数字就入栈 
        num.push(atof(param.c_str()));
    else// 遇到操作符就计算,并将结果入栈 
        cal(param, num);
}

int main()
{
    int n,i,index1,index2,count;
    string param;
    cin>>n;

    // 初始化memory
    priority_queue < double,vector<double>,greater<double> > p;
    vector<double> nums;
    for(i=0;i<n;i++)
    {
        double inData;
        cin>>inData;
        p.push(inData);
    }
    getchar();

    // 计算后缀表达式的值
    stack <double> bolan_num;
    string command;
    while(getline(cin,command))
    {
        index1=0,index2=command.length()-1;
        // 从右向左遍历表达式 获取操作符和数字
        for(i=0; i<=command.length(); i++)
            if(command[i]==' ' || command[i]=='\0')
            {
                index2=i;
                param=command.substr(index1, index2-index1);
                index1=index2+1;
                if(param=="=")
                {
                    // 用新计算出的值,替换掉memory中的最小值
                    printf("%e\n",bolan_num.top());
                    p.pop();
                    p.push(bolan_num.top());

                    bolan_num.pop();
                    if(!bolan_num.empty())
                        cout<<"expect empty"<<endl;
                }
				else
                    bolan(param, bolan_num);
            }
    }
    printf("\n");
    // 输出memory中的值
    count=0;
    for(i=1; i<=n; i++)
    {
        count++;
        if(i==n)
        	printf("%e",p.top());
        else if(count%10==0)
        	printf("%e\n",p.top());
        else
        	printf("%e ",p.top());
        p.pop();
    }
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值