JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Java 程式分享區 » Web  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
作者 算式運算器(beta)
roytsang





發文: 618
積分: 1
於 2011-06-14 10:14 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
這是我多年的夢想,想寫一個算式運算器,最近寫了一個,暫時只支援+-*/ 和^(次方),未支援括孤,
希望大家試試玩,看看有沒有bug,如果沒有問題,我才繼續。
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
<html>
  <body>
    <script type="text/javascript" src="Vector.js"></script>
    <script language=javascript>
      function Calculator(x)
      {
        var self=this,myX=x;
        var result="";
        var debugArea=document.getElementById("debug");
        var debug=true;
        var operators=new Vector();
        var operands=new Vector();
        if ((x==null) || (x==""))
        {
          throw "The entered expression is empty or null.";
        }
        else 
        {  
          if (hasInvalidCharacter(x))
          {
            throw "The entered expression contains invalid character.";
          }
          else
          {
            result="";
            debugArea.innerHTML="";
            parseExpression();
          }
        }
        function calculatePower()
        {
          var s,i,op1,op2,op;
          s=operators.getSize();
          for (i=0;i<s;i++)
          {
            op=operators.getElementAt(i);
            if (op.indexOf("^")>-1)
            {
              op1=operands.getElementAt(i);
              op2=operands.getElementAt(i+1);
              if ((op=="^") || (op=="^+"))
              {
                op1=Math.pow(op1,op2);
              }
              else
              {
                op1=Math.pow(op1,-op2);
              }
              operands.overwriteElementAt(op1,i);
              operands.removeElementAt(i+1);
              operators.removeElementAt(i);
              break;
            }
          }          
        }
        function calculateTimeDiv()        
        {
          var s,i,op1,op2,op;
          s=operators.getSize();
          for (i=0;i<s;i++)
          {
            op=operators.getElementAt(i);
            if ((op=="*")||(op=="/")||(op=="*-")||(op=="*+")||(op=="/-")||(op=="/+"))
            {
              op1=operands.getElementAt(i);
              op2=operands.getElementAt(i+1);
              switch (op)
              {
                case "*" :
                case "*+":op1=op1*op2;
                      break
                case "*-":op1=op1* (-op2);
                      break        
                case "/" :
                case "/+":op1=op1/op2;
                      break
                case "/-":op1=op1/(-op2);
                      break              
              }
              operands.overwriteElementAt(op1,i);
              operands.removeElementAt(i+1);
              operators.removeElementAt(i);
              break;
            }
          }          
        }
        function calculateAddSub()
        {
          var s,i,op1,op2,op;
          s=operators.getSize();
          for (i=0;i<s;i++)
          {
            op=operators.getElementAt(i);
            if ((op=="+")||(op=="-"))
            {
              op1=operands.getElementAt(i);
              op2=operands.getElementAt(i+1);
              if (op=="+") 
              {
                op1=op1*1.0+op2*1.0;
              }
              else
              {
                op1=op1-op2;
              }
              operands.overwriteElementAt(op1,i);
              operands.removeElementAt(i+1);
              operators.removeElementAt(i);
              break;
            }
          }          
        }
        this.calculate=function()
        {
          var op1,op2,oper;
          while (operators.contains("^")||operators.contains("^+")||operators.contains("^-"))
          {
            calculatePower();
            genResult();
          }
          while (operators.contains("/")||operators.contains("/+")||operators.contains("/-")||operators.contains("*")||operators.contains("*+")||operators.contains("*-"))
          {
            calculateTimeDiv();
            genResult();
          }
          while (operators.contains("+")||operators.contains("-"))
          {
            calculateAddSub();
            genResult();
          }
        }
        function parseExpression()
        {
          var epar=/[0-9]+\.?[0-9]*(e\+[0-9]*|e-[0-9]*|e[0-9]*)?/gi;
          var operatorList="+-/*^";
          var preIndex=-1,temp="",temp1="",temp2,counter=0;
          var tempOperands=myX.match(epar),op;
          
          //remove all operands for the expression string
          temp=myX;
          for (i=0;i<tempOperands.length;i++)
          {
            l=tempOperands[i].length;
            operands.insertElementAt(tempOperands[i],i);
            //result+=tempOperands[i]+"\n";
            temp1="";
            for (j=0;j<l;j++)
              temp1+=" ";
            temp=temp.replace(tempOperands[i],temp1);  
          }
 
          //remove all operator for the expression string
          temp2=temp;
          temp=temp.replace(/\+/g,"");
          temp=temp.replace(/-/g,"");
          temp=temp.replace(/\//g,"");
          temp=temp.replace(/\*/g,"");
          temp=temp.replace(/\^/g,"");
          temp=temp.replace(/ /g,"");
          
          if (temp=="")
          {
            for (i=0;i<temp2.length;i++)
            {
              if (operatorList.indexOf(temp2.substr(i,1))>-1)
              {
                op=temp2.substr(i,1);
                if (i==0)
                {
                  operands.overwriteElementAt(op+operands.getElementAt(0),0);
                  preIndex=i;
                }
                else
                {
                  if ((i-preIndex)>1)
                  {  
                    operators.insertElementAt(temp2.substr(i,1),counter);
                    preIndex=i;
                    counter++;  
                  }
                  else
                  {
                    temp=temp2.substr(preIndex,1)+temp2.substr(i,1);
                    
                    switch (temp)
                    {
                      case "-+":
                      case "+-":operators.overwriteElementAt("-",counter-1);
                            break;
                      case "++":
                      case "--":operators.overwriteElementAt("+",counter-1);  
                            break;
                      case "^+":
                      case "^-":
                      case "*-":
                      case "*+":
                      case "/-":
                      case "/+":operators.overwriteElementAt(temp,counter-1);
                            break;
                      default  :throw "The entered expression contains invalid operator sequence.";
                            break;                   
                    }
                  }
                }                    
              }    
            }
            if (operands.getSize()-operators.getSize()!=1)
            {
              throw "The entered expression contains invalid operator count.";
            }
            else
              genResult();
          }
          else
          {
            if (debug)
              debugArea.innerHTML+="temp="+temp+"<br>";
            throw "There is something wrong in entered expression.";
          }                  
        }
        this.getResult=function()
        {
          return result;
        }
        function genResult()
        {
          j=0;
          for (i=0;i<operators.getSize();i++)
          {
            result+=operands.getElementAt(i)+operators.getElementAt(i);
          }
          result+=operands.getElementAt(i)+",";
          
        }
        
        function hasInvalidCharacter(j)
        {
          var hasInvalidCharacter=false;
          var apar=/^[\d+-]/gi;
          if (!apar.test(j))
          {
            hasInvalidCharacter=true;
            if (debug)
              debugArea.innerHTML+="apar.test failed<br>";
          }
          var bpar=/[a-d,f-z]/gi; //contain a-d and f-z character
          if ((!hasInvalidCharacter) && bpar.test(j))
          {
            hasInvalidCharacter=true;
            if (debug)
              debugArea.innerHTML+="bpar.test failed<br>";
          }
          var cpar=/^[+-]\D/gi;   //starts with +- and followed with non-digit character
          if ((!hasInvalidCharacter) && cpar.test(j))
          {
            hasInvalidCharacter=true;
            if (debug)
              debugArea.innerHTML+="cpar.test failed";
          }
          var dpar=/\.\D+/i;      //decimal point followed with non-digit character
          if ((!hasInvalidCharacter) && dpar.test(j))
          {
            hasInvalidCharacter=true;
            if (debug)
              debugArea.innerHTML+="dpar.test failed<br>";
          }          
          var epar=/e$/i;      //not ends with "E"
          if ((!hasInvalidCharacter) && epar.test(j))
          {
            hasInvalidCharacter=true;
            if (debug)
              debugArea.innerHTML+="epar.test failed<br>";
          }
          var fpar=/\De\?/i;    //non digit character follow the character "e";
          if ((!hasInvalidCharacter) && fpar.test(j))
          {
            hasInvalidCharacter=true;
            if (debug)
              debugArea.innerHTML+="fpar.test failed<br>";
          }          
          return (hasInvalidCharacter);
          
        }            
      }  
      function getResult(v)
      {
        var myExp=v.expression.value;
        v.expression.value=myExp;
        var resultArea=document.getElementById("resultArea");
        var i,c,calculationResult,finishObject=document.createElement("sup");
        try
        {
          c=new Calculator(myExp);
          resultArea.innerHTML=myExp+"<br><hr>";
          c.calculate();
          calculationResult=c.getResult().split(",");
          for (i=0;i<calculationResult.length-2;i++)
            resultArea.innerHTML+="="+calculationResult[i]+"<br>";
          resultArea.innerHTML+="=<span style='border-bottom: 3px double;'>"+calculationResult[i]+"</span>";
          c=null;
        }
        catch (er)
        {
          resultArea.innerHTML="<font color=red>"+er+"</font><br>";
        }    
      }            
    </script>
    Arithmetic Expression Solver
    
    <form action="" method="post" onsubmit="getResult(this);return false;">
      <table>
        <tr>
           <td>Please input the expression</td>
        </tr>
        <tr>
          <td>    
          <input type=text value="1*0.3+2^6/8e+0-5.9+3-4" name="expression">
          <input type=submit value="Get Result">
        </td>
        </tr>      
       </table> 
    </form>
    <div id="resultArea">
    </div>
    <div id="debug">
    </div>
  </body>
</html>          
 


Vector.js (8.26k)


roytsang edited on 2011-06-14 10:20
reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
ace33022





發文: 28
積分: 0
於 2011-06-14 21:28 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
下載試用看看,最近正在學習JS的物件設計方法,這個範例給我不少學習的機會Smile

reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
tkcn





發文: 59
積分: 0
於 2011-06-15 14:00 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
這程式有個 bug,
power 應該是右結合律,也就是說當 expression 為 2^3^4 時,
應該被視為 2^(3^4),而不是目前的作法 (2^3)^4。

另外,我必須提一下,
這個題目已經被研究得十分透徹了,
也已經有了很簡潔的實作方式。

如果你的目的是 "開發一個算式運算器",
那不妨先看看別人是怎麼做的、做到什麼地步。

中序轉後序:
http://en.wikipedia.org/wiki/Shunting-yard_algorithm

轉成後序後,計算變得相對容易許多:
http://en.wikipedia.org/wiki/Reverse_Polish_Notation

當然如果只是想試試看自己重新開發一個演算法,就又另當別論了


reply to postreply to post
作者 Re:算式運算器(beta) [Re:tkcn]
roytsang





發文: 618
積分: 1
於 2011-06-15 16:28 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
我估計應該有algorithm解決這問個題的,
可是我不知道在google放什麼keyword來找,
先用自己方法來develop,現在我來研究這兩個algorithm吧

最後謝謝你的提點


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
roytsang





發文: 618
積分: 1
於 2011-07-06 14:05 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
剛剛我用了這兩個算法再做了一個算式運算器程式,可是它在計算以下算式時出錯,

8-0*4-3

網址如下:
http://cstsang.no-ip.com/css&dhtml/bv3.htm

可是計算其他算式時又沒有問題。
各位大大如果有興趣可以到以上網址,我已經將計算過程顯示出來可是找不到出錯原因。


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
asdfvg0000





發文: 1
積分: 0
於 2011-07-06 15:22 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
還有像是9-1*3-5這個也是錯的

9-1*3-5使用網頁整個運算過程變成

9-1*3-5=9-(1*3)-5=9-3-5=9-(3-5)=9-(-2)=11

你發現哪邊有問題了嗎?

當做完中間的乘法之後,應該要由左至右開始運算,可是變成從右至左開始運算。


reply to postreply to post
作者 Re:算式運算器(beta) [Re:asdfvg0000]
roytsang





發文: 618
積分: 1
於 2011-07-07 09:16 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
照你這樣說,這豈不是一個recursive process嗎?
除了乘法之外,還有什麼情況,需要由頭做起呢?


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
jfire





發文: 128
積分: 0
於 2011-07-07 10:19 user profilesend a private message to usersend email to jfirereply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
這題是運算符號優先權問題…

用運算符號權值表就解決了


reply to postreply to post
作者 Re:算式運算器(beta) [Re:jfire]
roytsang





發文: 618
積分: 1
於 2011-07-07 12:17 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
好像成功了!!!
http://cstsang.no-ip.com/css&dhtml/bv3.htm


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
roytsang





發文: 618
積分: 1
於 2011-07-07 13:36 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
又失敗了

reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
roytsang





發文: 618
積分: 1
於 2011-07-07 15:05 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
終於改好了,成功可以用了。

reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
roytsang





發文: 618
積分: 1
於 2012-08-30 22:10 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
現在除了計算出答案外,還能夠顯示計算途中的步驟,歡迎試玩:
http://cstsang.gossipcafe.hk/css&dhtml/bv8.htm


roytsang edited on 2013-06-15 15:31
reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
jack850628





發文: 6
積分: 0
於 2016-12-19 09:40 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
有BUG
當運算子後面跟著正號或負號就不能計算
像是1*-2


reply to postreply to post
System.out.println("Hello World!");
作者 Re:算式運算器(beta) [Re:jack850628]
roytsang





發文: 618
積分: 1
於 2016-12-19 09:52 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
這不是bug,試試這個吧
1*(-2)


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
roytsang





發文: 618
積分: 1
於 2018-11-07 14:51 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
這個加強版可以給大家試玩:
http://cstsang.gossipcafe.hk/css&dhtml/Calculator/bv10.html


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2018-11-09 10:00 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
關於運算式的部份:
https://openhome.cc/Gossip/Toy/Operator.html

把那些 if..else 抽出來成為節點,程式碼會比較好維護。

然後,就可以試著發展,看看能否成為一門語言了 … XD
https://openhome.cc/Gossip/Toy/


reply to postreply to post
良葛格學習筆記
作者 Re:算式運算器(beta) [Re:caterpillar]
roytsang





發文: 618
積分: 1
於 2018-11-09 16:55 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
首先,良大來看我的程式碼,真是受寵若驚,先行謝過。
但是有些東西想弄清楚,你意思是不是我以下這個.js file:
http://cstsang.gossipcafe.hk/css&dhtml/Calculator/Operator.js

可以根據你以下這個網頁的方向來改進呢?
https://openhome.cc/Gossip/Toy/Operator.html

其實這個程式已經放下幾年了,只是我在看舊post 看到我的舊程式有問題,
想去fix 它時,發現完本的程式碼根本不好維護,所以有重寫念頭,在今次重寫的旅程裡,
我發現之前寫的code 好像連基本四則運算的概念(今次感受最深的昰原來解算式是一recursive process 來的,
不知道是不是良大所講的context 呢?),都沒有跟隨,只是見招拆招而已,所以容易出錯,很難擴充。

至於會不會發展成為一個新的電腦語言,這個念頭曾經在我腦海閃過,畢竟要發展一個語言不是一個人可以做到事,
我想隨緣吧。


roytsang edited on 2018-11-09 17:02
reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2018-11-10 00:52 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
解算式或程式語法,都是一種 recursive process,當然,可以使用迴圈與 if..else 等來處理,不過,很容易就一堆 if..else..while...if..else..while 的巢狀。

分解為語法節點,每個節點獨立處理,漸漸地,就可以開展為小語言。

context 是提供運算當時的相關資訊,例如若有設定變數,context 可以是查找變數的來源之一等。


reply to postreply to post
良葛格學習筆記
作者 Re:算式運算器(beta) [Re:roytsang]
yjy198410





發文: 27
積分: 0
於 2018-11-11 03:50 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
記得以前學資料結構時有幾種處理方式:infix(中序運算), prefix(前序運算), post(後序運算)。都要搭配堆疊來操作。

如果是現成的API:
JS可參考:
http://mathjs.org/docs/expressions/parsing.html

Java 可參考:
http://mathparser.org/


reply to postreply to post
十年磨一劍,我老是在磨劍。那怕磨劍不成,鐵杵磨成繡花針。
琢磨JSF, JavaFX, Design Pattern
作者 Re:算式運算器(beta) [Re:caterpillar]
roytsang





發文: 618
積分: 1
於 2018-11-29 08:53 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
caterpillar wrote:
解算式或程式語法,都是一種 recursive process,當然,可以使用迴圈與 if..else 等來處理,不過,很容易就一堆 if..else..while...if..else..while 的巢狀。

分解為語法節點,每個節點獨立處理,漸漸地,就可以開展為小語言。

context 是提供運算當時的相關資訊,例如若有設定變數,context 可以是查找變數的來源之一等。

原來良大說的algorithm 和我實作的alogrithm是兩碼子的事,
我是用shunting yard algorithm,良大說的是Recursive Descent,
怪不得不明白良大在說什麼。


reply to postreply to post
作者 Re:算式運算器(beta) [Re:roytsang]
javaX





發文: 188
積分: 0
於 2018-11-30 03:19 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
都是別人的文學作品

reply to postreply to post
教育部:要如何保證畢業即就業
經濟部:所以公司都是我開的
財政部:發前單位請不要幻想能春風化雨
行政院:為什麼該單位發錢的時候都想去當老師
» JWorld@TW »  Java 程式分享區 » Web

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8