Perl四则运算

#######################################
#just use for practice
#######################################

#!/usr/bin/perl						#use warning
#use diagnostics;					#use diagnositc
#use warnings;						#use warning
#use strict;						#use strict
#This means you MUST always use
#-------------MY---------------
#before you new any variants

#use strict;

###############################################################
#用Perl实现的四则运算,可以处理括号。但是没有考虑太多异常系。
#比如括号数量不匹配,或者输入了非括号,非加减乘除好等。
#
#基本思路为有括号,则进行递归,找到第一个最小的括号,递归之。
#计算出结果后,替换整个括号内容。比如(1+3),整体替换为数字4。
#由于每次递归到最后到最后,将会是只有左右括号,中间是不包含
#括号的算式。此时进行普通运算。
#从头开始匹配,如果找到数字,则压入数字栈。找到符号,则压入
#符号栈。在找到*/号的时候,立马取出前一个数字,与当前数字计算,
#然后压入数字栈。在照完第一遍以后,栈中只剩下数字和加减号。
#依次取出一个符号,和两个数字计算,知道栈中为空。
#最后的结果即为最终的结果。
###############################################################
$in_expression="(1+1)*(3*(2+2))"; #你的表达式写在这里。这个也可以改为手动输入

print "Your expression is:\n$in_expression\n\n";

$ans=&cal($in_expression);			#调用函数,参数为第二个数

sub cal()
{
########################################################################################################
	my $ret=0;
    my $para=$_[0];					#获取传入的参数值
	while($para=~/\(.*?\)/)			#只要参数还有括号(),就进行处理,要么去掉开头括号,要么进行递归
	{
		if($para=~/^\([^\(]*?\)$/)		#在以前括号 "(" 开头,后括号 ")" 结尾, 而且中间全是非前括号 "(" 的情况下, 去头尾
		{
			$para=~s/^\(//;				#去掉前括号 (
			$para=~s/\)$//;				#去掉后括号 )
		}
		if($para=~/\([^\(]*?\)/)		#将第一组有括号的字符串进行递归
		{        
			$ret=&cal($&);
			$para=~s/\([^\(]+?\)/$ret/;	#算出了第一个括号内的值,把它用来替换第一个括号的整体内容(包括括号)
										#用非贪婪的来限定为第一个括号
			$cnt++;
			print "$cnt. $para\n";
		}
	}
#以上为对括号的运算,有括号的情况下,需要去掉括号或者递归
########################################################################################################
#以下为没有括号的情况下,进行的四则运算
    my @my_num=();						#用来存储数字
    my @my_ope=();						#用来存储运算符

    while($para ne '')					#while not complete
    {
        if($para=~s/^(\d+)//)			#find the numbers
        {
            push @my_num,$1;			#store the numbers
        }
        if($para=~s/(\D+?)//)			#find the operators
        {
			#------------------------------------------------------------------
			#以下优先度较高的乘除运算,立马取出前一个数字,与当前数字进行计算
            if($1 eq '*')
            {
                if($para=~s/^(\d+)//)	#if there is a number after '*'
                {
                    $tmp_L=pop @my_num;
					$tmp_R=$1;
                    $tmp=$tmp_L*$tmp_R;
                    push @my_num,$tmp;	#push the caled number to @my_num
                }
            }
            elsif($1 eq '/')
            {
                if($para=~s/^(\d+)//)	#if there is a number after '/'
				{
                    $tmp_L=pop @my_num;
					$tmp_R=$1;
                    $tmp=$tmp_L/$tmp_R;
                    push @my_num,$tmp;	#push the caled number to @my_num
                }        
            }
			#以上优先度较高的乘除运算,立马取出前一个数字,与当前数字进行计算
			#------------------------------------------------------------------
            else						#加减符号,先存储起来
            {
                push @my_ope,$1;		#store the operators        
            }
        }
    }
########################################################################################################
#乘除符号已经处理完毕,此时只剩下加减符号,从后向前进行处理也是可以的。(因为加法结合律)
    while(@my_ope!=0)
    {
        if(pop @my_ope eq '+')			#感觉这里基本不需要注释了
        {
            $tmp_R=pop @my_num;
            $tmp_L=pop @my_num;
            $tmp=$tmp_L+$tmp_R;
            push @my_num,$tmp;
        }
        elsif(pop @my_ope eq '-')
        {
            $tmp_R=pop @my_num;
            $tmp_L=pop @my_num;
            $tmp=$tmp_L-$tmp_R;
            push @my_num,$tmp;
        }
    }
    return pop @my_num;
}
print "\nThe result is: $ans\n";
########################################################################################################

#######################################
#######################################
print "\n\n\n";
print "Press any key to exit...";
<>;		#Stop to show the result








  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值