基于JavaScript的公式解释器 - 11 【函数的实现】
2010-10-19 07:04
716 查看
FunctionBase 函数基类
文件:FunctionBase.js
注意,这里的的实现是:公式解析时可以没有函数定义,而在公式解释时对通过全局$FunctionMapper表进行函数名查找。相应的,
函数在需要通过$RegisterFunction进行注册。
因为可以不知道函数的先验知识,所以需要一个定义来表示函数,该定义就是FunctionUnknown类。
FunctionUnknown类
文件:FunctionBase.js
各类函数的实现
这里没有实现全部Excel函数,仅有“常用”目录下的几个,其中PMT的公式未知,所以也没有实现,留待家庭作业吧:-P。
文件:FunctionBase.js
var $FunctionMapper = []; // Global function mapper function $RegisterFunction(funcObj) { if ($FunctionMapper[funcObj.get_FunctionName().toLowerCase()] != null) throw new Exception(this, "$RegisterFunction:" + funcObj.get_FunctionName() + " has registered"); $FunctionMapper[funcObj.get_FunctionName().toLowerCase()] = funcObj; }; function $GetRegisterFunction(funcname) { if ($FunctionMapper[funcname.toLowerCase()] != null) return $FunctionMapper[funcname.toLowerCase()]; else return null; } // --------------- FunctionBase -------------- function FunctionBase() { this.DeriveFrom(new OperatorBase()); this.set_ClassName("FunctionBase"); this._type = new FunctionType("undefined"); }; FunctionBase.prototype = { get_FunctionName: function() { return this.get_Sign(); }, Evaluate: function(args) { throw new Exception(this, "Not implemented"); } // Evaluate }; // FunctionBase.prototype
注意,这里的的实现是:公式解析时可以没有函数定义,而在公式解释时对通过全局$FunctionMapper表进行函数名查找。相应的,
函数在需要通过$RegisterFunction进行注册。
因为可以不知道函数的先验知识,所以需要一个定义来表示函数,该定义就是FunctionUnknown类。
FunctionUnknown类
文件:FunctionBase.js
// ------------- FunctionUnknown ------------------ // Used for function parser function FunctionUnknown(arg) { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionUnknown"); if (arg != null) this.set_Sign(arg.ToString()); else this.set_Sign("undefined"); }; FunctionUnknown.prototype.Evaluate = function(args) { var values = []; for(var i = 0; i < args.length; i++) values.push(args[i].get_Value()); $Debug.WriteLine("Undefined function:" + this.get_Sign() + "(" + values.join(",") + "), assume return 0."); return new OperandNumber(0); }; // Register operation should be performed after the prototype defined. $RegisterFunction(new FunctionUnknown());
各类函数的实现
这里没有实现全部Excel函数,仅有“常用”目录下的几个,其中PMT的公式未知,所以也没有实现,留待家庭作业吧:-P。
/// Function Template /* function FunctionXXX() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionXXX"); this.set_Sign("XXX"); }; FunctionXXX.prototype.Evaluate = function(args) { // should return a value }; $RegisterFunction(new FunctionXXX()); */ /////////////////////////////////////////// // SUM /////////////////////////////////////////// function FunctionAverage() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionAverage"); this.set_Sign("Average"); }; FunctionAverage.prototype = { Evaluate: function(args) { var res = 0; for (var i = 0; i < args.length; i++) { if (!(args[i].IsNumber() || args[i].IsBoolean())) throw new Exception(this, "Evaluate", "Unsupported argument:" + $T(args[i])); res += args[i].get_Value(); } return new OperandNumber(res / args.length); } }; $RegisterFunction(new FunctionAverage()); /////////////////////////////////////////// // Average /////////////////////////////////////////// function FunctionSum() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionSum"); this.set_Sign("Sum"); }; FunctionSum.prototype.Evaluate = function(args) { var res = 0; for (var i = 0; i < args.length; i++) { if (!(args[i].IsNumber() || args[i].IsBoolean())) throw new Exception(this, "Evaluate", "Unsupported argument:" + $T(args)); res += args[i].get_Value(); } return new OperandNumber(res); }; $RegisterFunction(new FunctionSum()); /////////////////////////////////////////// // IF /////////////////////////////////////////// function FunctionIF() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionIF"); this._type = new FunctionType("IF", 3); }; FunctionIF.prototype.Evaluate = function(args) { if (!args[0].IsBoolean()) throw new Exception(this, "Evaluate", "First argument should be boolean"); return args[0].get_Value() ? args[1] : args[2]; }; $RegisterFunction(new FunctionIF()); /////////////////////////////////////////// // Count /////////////////////////////////////////// /////////////////////////////////////////// // Max /////////////////////////////////////////// function FunctionMax() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionMax"); this.set_Sign("Max"); }; FunctionMax.prototype.Evaluate = function(args) { var res = 0; for(var i = 1; i < args.length; i++) if (args[i].IsNumber()) if (res < args[i].get_Value()) res = args[i].get_Value(); return new OperandNumber(res); }; $RegisterFunction(new FunctionMax()); /////////////////////////////////////////// // Min /////////////////////////////////////////// /////////////////////////////////////////// // Sin /////////////////////////////////////////// function FunctionSin() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionSin"); this._type = new FunctionType("Sin", 1); }; FunctionSin.prototype.Evaluate = function(args) { return new OperandNumber(Math.sin(args[0].get_Value())); }; $RegisterFunction(new FunctionSin()); /////////////////////////////////////////// // SUMIF /////////////////////////////////////////// function FunctionSumIF() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionSumIF"); this.set_Sign("SumIF"); }; FunctionSumIF.prototype.Evaluate = function(args) { // Depend on Cell throw new Exception(this, "Evaluate", "Not implemented"); }; $RegisterFunction(new FunctionSumIF()); /////////////////////////////////////////// // PMT /////////////////////////////////////////// function FunctionPMT() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionPMT"); this.set_Sign("PMT"); }; FunctionPMT.prototype.Evaluate = function(args) { throw new Exception(this, "Evaluate", "Not implemented"); }; $RegisterFunction(new FunctionPMT()); /////////////////////////////////////////// // STDEV /////////////////////////////////////////// function FunctionSTDEV() { this.DeriveFrom(new FunctionBase()); this.set_ClassName("FunctionSTDEV"); this.set_Sign("STDEV"); }; FunctionSTDEV.prototype.Evaluate = function(args) { var squareSum = 0, sum = 0; for(var i = 0; i < args; i++) { squareSum += args[i].get_Value() * args[i].get_Value(); sum += args[i].get_Value(); } var res = Math.sqrt((args.length * squareSum - sum * sum) / (args.length * (args.length - 1))); return new OperandNumber(res); }; $RegisterFunction(new FunctionSTDEV());
相关文章推荐
- 基于JavaScript的公式解释器 - 5 【一元操作符的实现】
- 基于JavaScript的公式解释器 - 13 【公式估值器的实现】
- 基于JavaScript的公式解释器 - 6 【二元操作符基类的实现】
- 基于JavaScript的公式解释器 - 7 【算术操作符的实现】
- 基于JavaScript的公式解释器 - 8 【比较操作符的实现】
- 基于JavaScript的公式解释器 - 9 【逻辑操作符的实现】
- 基于JavaScript的公式解释器 - 10 【位操作符的实现】
- 基于JavaScript的公式解释器 - 3 【操作数类型的实现】
- 基于JavaScript的公式解释器 - 4 【操作符基类型的实现】
- 基于JavaScript的公式解释器 - 12 【公式解析器】
- 基于遗传算法计算函数最大值--JavaScript实现
- 基于JavaScript的公式解释器 - 1 【设计】
- JavaScript面向对象-基于函数伪造的方式实现继承
- 基于JavaScript的公式解释器 - 14 【单元格对象】
- 基于JavaScript的公式解释器 - 15 【单元格范围对象】
- 基于JavaScript的公式解释器 - 2 【完善自己的类型系统】
- 基于JavaScript的公式解释器 - 16 【MailStone,测试】
- 基于JavaScript实现一定时间后去执行一个函数
- JavaScript面向对象-基于原型链和函数伪装组合的方式实现继承
- JavaScript基于自定义函数判断变量类型的实现方法