#######################################
#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
Perl四则运算
最新推荐文章于 2022-01-15 01:20:01 发布