本表达式求值程序支持加减乘除、乘方开方、括号嵌套,精确度约为十几位小数,并支持小数和多位数录入计算。支持最长 4GB 的表达式。
版权所有 Ceeji,保留所有权利。转载请注明出处并保留本注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 
//By Ceeji 
//Date: 2009-4-16 
//Type: Stack 
//State: Accepted 
//For LL 
//简要说明:支持加减乘除、乘方开方、括号嵌套,精确度约为十几位小数,并支持小数和多位数录入计算。支持最长 4GB 的表达式。 
//版权所有,保留所有权利。使用时必须保留注释。 
Program biaodashi; 
Const p='+-*/^()#'; 
      c:array[1..8,1..8]of integer= 
          {+  -  *  /  ^  (  )  #} 
 {+}     ((1, 1, 0, 0, 0, 0, 1, 1), 
 {-}      (1, 1, 0, 0, 0, 0, 1, 1), 
 {*}      (1, 1, 1, 1, 0, 0, 1, 1), 
 {/}      (1, 1, 1, 1, 0, 0, 1, 1), 
 {^}      (1, 1, 1, 1, 1, 0, 1, 1), 
 {(}      (0, 0, 0, 0, 0, 0, 2, 1), 
 {)}      (3, 3, 3, 3, 3, 3, 3, 3), 
 {#}      (0, 0, 0, 0, 0, 0, 0, 2) 
          ); 
Var i,j,k:longint; 
    a,jg:extended; 
    s:ansistring; 
 
//计算两个数加减乘除或乘方,支持小数指数。 
Function jisuan(shu1,shu2:extended; k:longint):extended; 
Var jg:extended; 
begin 
    case k of 
    1: jg:=shu1+shu2; 
    2: jg:=shu1-shu2; 
    3: jg:=shu1*shu2; 
    4: jg:=shu1/shu2; 
    5: jg:=exp(shu2*ln(shu1)); 
    end; 
    jisuan:=jg; 
end; 
//把带有空格的表达式转换为标准表达式以便进行计算。本程序为辅助子程序。 
Function guifan(st:ansistring):ansistring; 
var sn,ste:ansistring; 
    i,j,max:integer; 
begin 
   i:=0; 
   sn:=st; 
   max:=length(st); 
   while i<max do 
   begin 
       i:=i+1; 
       if sn[i]=' ' then 
       begin 
          for j:=i+1 to max do 
          begin 
             sn[j-1]:=sn[j]; 
          end; 
          max:=max-1; 
          i:=i-1; 
          continue; 
       end; 
   end; 
   guifan:=copy(sn,1,max); 
end; 
 
//计算表达式子程序。主要的子程序。 
Function jisuanbiaodashi(st:ansistring):extended;  // st: 要计算的表达式。返回值为 extended,精确度比较高。 
var i,j,k,ls,lf,t,len:longint; 
    x:extended; 
    b,bb:boolean; 
    shu:array[1..100]of extended; 
    fu :array[1..100]of longint; 
    s  :ansistring; 
begin 
    fillchar(shu,sizeof(shu),0); 
    fillchar(fu,sizeof(fu),0); 
    s:='#'+st+'#'; 
    ls:=0; lf:=0; i:=0; 
    len:=length(s); 
    repeat 
    begin 
        shu[ls+1]:=0; 
        b:=false; 
        bb:=false; 
        i:=i+1; 
        while (((s[i]>='0')and(s[i]<='9')))or(s[i]='.') do 
        begin 
            b:=true; 
            if (s[i]<>'.')and(bb=false) then 
            begin 
               val(s[i],x); 
               shu[ls+1]:=10*shu[ls+1]+x; 
               i:=i+1; 
               continue; 
            end; 
            if s[i]='.' then begin bb:=true; i:=i+1; t:=i-1; continue; end; 
            if bb=true then 
            begin 
               val(s[i],x); 
               shu[ls+1]:=shu[ls+1]+ x*1/exp((i-t)*ln(10)); 
               i:=i+1; 
               continue; 
            end; 
        end; 
        if b=true then begin ls:=ls+1; i:=i-1; continue; end; 
        k:=pos(s[i],p); 
        if (k=0)or(k>8) then begin writeln('error'); exit; end; 
        inc(lf); 
        fu[lf]:=k; 
        while (lf>1)and(c[fu[lf-1],fu[lf]]<>0)do begin 
           if c[fu[lf-1],fu[lf]]=2 then 
           begin 
              dec(lf,2); 
              continue; 
           end; 
           shu[ls-1]:=jisuan(shu[ls-1],shu[ls],fu[lf-1]); 
           dec(ls); 
           dec(lf); 
           fu[lf]:=fu[lf+1]; 
        end; 
    end; 
    until i>=len; 
    jisuanbiaodashi:=shu[1]; 
end; 
 
begin 
   readln(s); 
   jg:=jisuanbiaodashi(guifan(s)); 
   writeln(jg:0:3); //保留三位小数。可以修改这个数值以便获得更高的精度。 
   readln; 
end.{main}