基於JavaScript的公式解譯器 – 11 【函數的實現】

來源:互聯網
上載者:User

FunctionBase 函數基類

檔案:FunctionBase.js

var $FunctionMapper = [];</p><p>// Global function mapper<br />function $RegisterFunction(funcObj) {<br /> if ($FunctionMapper[funcObj.get_FunctionName().toLowerCase()] != null)<br /> throw new Exception(this, "$RegisterFunction:" + funcObj.get_FunctionName() + " has registered");</p><p> $FunctionMapper[funcObj.get_FunctionName().toLowerCase()] = funcObj;<br />};</p><p>function $GetRegisterFunction(funcname)<br />{<br /> if ($FunctionMapper[funcname.toLowerCase()] != null)<br /> return $FunctionMapper[funcname.toLowerCase()];<br /> else<br /> return null;<br />}</p><p>// --------------- FunctionBase --------------<br />function FunctionBase() {<br /> this.DeriveFrom(new OperatorBase());<br /> this.set_ClassName("FunctionBase");<br /> this._type = new FunctionType("undefined");<br />};</p><p>FunctionBase.prototype = {<br /> get_FunctionName: function() { return this.get_Sign(); },<br /> Evaluate: function(args) {<br /> throw new Exception(this, "Not implemented");<br /> } // Evaluate<br />}; // FunctionBase.prototype<br />

 

注意,這裡的的實現是:公式解析時可以沒有函數定義,而在公式解釋時對通過全域$FunctionMapper表進行函數名尋找。相應的,

函數在需要通過$RegisterFunction進行註冊。

因為可以不知道函數的先驗知識,所以需要一個定義來表示函數,該定義就是FunctionUnknown類。

 

FunctionUnknown類

檔案:FunctionBase.js

// ------------- FunctionUnknown ------------------<br />// Used for function parser<br />function FunctionUnknown(arg) {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionUnknown");</p><p> if (arg != null)<br /> this.set_Sign(arg.ToString());<br /> else<br /> this.set_Sign("undefined");<br />};</p><p>FunctionUnknown.prototype.Evaluate = function(args) {<br /> var values = [];</p><p> for(var i = 0; i < args.length; i++)<br /> values.push(args[i].get_Value());</p><p> $Debug.WriteLine("Undefined function:" + this.get_Sign() + "(" + values.join(",") + "), assume return 0.");<br /> return new OperandNumber(0);<br />};</p><p>// Register operation should be performed after the prototype defined.<br />$RegisterFunction(new FunctionUnknown());

 

各類函數的實現

這裡沒有實現全部Excel函數,僅有“常用”目錄下的幾個,其中PMT的公式未知,所以也沒有實現,留待家庭作業吧:-P。

/// Function Template<br />/*<br />function FunctionXXX() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionXXX");<br /> this.set_Sign("XXX");<br />};</p><p>FunctionXXX.prototype.Evaluate = function(args) {</p><p> // should return a value<br />};</p><p>$RegisterFunction(new FunctionXXX());<br />*/</p><p>///////////////////////////////////////////<br />// SUM<br />///////////////////////////////////////////<br />function FunctionAverage() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionAverage");<br /> this.set_Sign("Average");<br />};</p><p>FunctionAverage.prototype = {<br /> Evaluate: function(args) {<br /> var res = 0;</p><p> for (var i = 0; i < args.length; i++) {<br /> if (!(args[i].IsNumber() || args[i].IsBoolean()))<br /> throw new Exception(this, "Evaluate", "Unsupported argument:" + $T(args[i]));</p><p> res += args[i].get_Value();<br /> }</p><p> return new OperandNumber(res / args.length);<br /> }<br />};</p><p>$RegisterFunction(new FunctionAverage());</p><p>///////////////////////////////////////////<br />// Average<br />///////////////////////////////////////////<br />function FunctionSum() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionSum");<br /> this.set_Sign("Sum");<br />};</p><p>FunctionSum.prototype.Evaluate = function(args) {<br /> var res = 0;</p><p> for (var i = 0; i < args.length; i++) {<br /> if (!(args[i].IsNumber() || args[i].IsBoolean()))<br /> throw new Exception(this, "Evaluate", "Unsupported argument:" + $T(args));</p><p> res += args[i].get_Value();<br /> }</p><p> return new OperandNumber(res);<br />};</p><p>$RegisterFunction(new FunctionSum());</p><p>///////////////////////////////////////////<br />// IF<br />///////////////////////////////////////////<br />function FunctionIF() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionIF");<br /> this._type = new FunctionType("IF", 3);<br />};</p><p>FunctionIF.prototype.Evaluate = function(args) {<br /> if (!args[0].IsBoolean())<br /> throw new Exception(this, "Evaluate", "First argument should be boolean");</p><p> return args[0].get_Value() ? args[1] : args[2];<br />};</p><p>$RegisterFunction(new FunctionIF());</p><p>///////////////////////////////////////////<br />// Count<br />///////////////////////////////////////////</p><p>///////////////////////////////////////////<br />// Max<br />///////////////////////////////////////////<br />function FunctionMax() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionMax");<br /> this.set_Sign("Max");<br />};</p><p>FunctionMax.prototype.Evaluate = function(args) {<br /> var res = 0;</p><p> for(var i = 1; i < args.length; i++)<br /> if (args[i].IsNumber())<br /> if (res < args[i].get_Value())<br /> res = args[i].get_Value();</p><p> return new OperandNumber(res);<br />};</p><p>$RegisterFunction(new FunctionMax());</p><p>///////////////////////////////////////////<br />// Min<br />///////////////////////////////////////////</p><p>///////////////////////////////////////////<br />// Sin<br />///////////////////////////////////////////<br />function FunctionSin() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionSin");<br /> this._type = new FunctionType("Sin", 1);<br />};</p><p>FunctionSin.prototype.Evaluate = function(args) {<br /> return new OperandNumber(Math.sin(args[0].get_Value()));<br />};</p><p>$RegisterFunction(new FunctionSin());</p><p>///////////////////////////////////////////<br />// SUMIF<br />///////////////////////////////////////////<br />function FunctionSumIF() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionSumIF");<br /> this.set_Sign("SumIF");<br />};</p><p>FunctionSumIF.prototype.Evaluate = function(args) {</p><p> // Depend on Cell<br /> throw new Exception(this, "Evaluate", "Not implemented");<br />};</p><p>$RegisterFunction(new FunctionSumIF());</p><p>///////////////////////////////////////////<br />// PMT<br />///////////////////////////////////////////<br />function FunctionPMT() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionPMT");<br /> this.set_Sign("PMT");<br />};</p><p>FunctionPMT.prototype.Evaluate = function(args) {</p><p> throw new Exception(this, "Evaluate", "Not implemented");<br />};</p><p>$RegisterFunction(new FunctionPMT());<br />///////////////////////////////////////////<br />// STDEV<br />///////////////////////////////////////////<br />function FunctionSTDEV() {<br /> this.DeriveFrom(new FunctionBase());<br /> this.set_ClassName("FunctionSTDEV");<br /> this.set_Sign("STDEV");<br />};</p><p>FunctionSTDEV.prototype.Evaluate = function(args) {<br /> var squareSum = 0,<br /> sum = 0;</p><p> for(var i = 0; i < args; i++) {<br /> squareSum += args[i].get_Value() * args[i].get_Value();<br /> sum += args[i].get_Value();<br /> }</p><p> var res = Math.sqrt((args.length * squareSum - sum * sum) / (args.length * (args.length - 1)));</p><p> return new OperandNumber(res);<br />};</p><p>$RegisterFunction(new FunctionSTDEV());

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.