js计算器组件Calc.js

来源:互联网 发布:查看交换机端口ip 编辑:程序博客网 时间:2024/06/05 04:15

js浮点型

在编程语言中关于浮点型数字计算问题的解决方案有很多种,其实很多人都会根据个人爱好进行封装,那么首先探讨一下浮点型小数计算存在什么问题。计算机存储的数据是二进制数据,也即1、0,那么在数学中的十进制数据如何映射为二进制数?对于整数,可以除于2取余数,最后倒叙排列来得出二进制编码(负数则数取补码),例如10的二进制为1010,而-10的二进制为0110,当然看你的计算机是32位还是64位,表示数据的精度不同。对于浮点数,常有乘法表示和除法表示两种(基数为2),对于除法,当小数位大于2-n次方时(0.5,0.25,0.125,…)表示1,小于当前2-n次方为0,最后可以得出小数的二进制,例如0.5 二进制为0.1,0.52的二进制为1000010…(后面无穷),因为表示不过来,所以要截取一定的位数来近似表示,例如这里的0.52的二进制为0.10000101。我们都知道在js中进行0.1+0.2=0.30000000000000004而不是0.3,就是因为截取了小数的二进制位数造成。所以在js中进行浮点数计算时,都是在精度特定的情况下进行。


(function(win) {    //计算器    var Calc = {                add: add, substract: substract, multiply:  multiply, divid: divid,         setScale: _setScale, scale: 2, isNumeric: _isNumeric,equal: equal,        getInstance: function() {            var instance = {};            //继承类            for(var name in Calc) {                if(name != "getInstance") {                    instance[name] = Calc[name];                }            }            return instance;        }           };    //加法    function add() {        var i = 0, len = arguments.length, sum = 0,            arg1 = this.isNumeric(arguments[0]) && arguments[0] || 0,            arg2 = this.isNumeric(arguments[1]) && arguments[1] || 0;        sum = _add.call(this, arg1, arg2);        if(len > 2) {            //用递归实现就是方便            sum = _add.call(this, sum, this.add.apply(this, Array.prototype.slice.call(arguments,2)));        }        return sum;    }    //两个数相加    function _add(arg1, arg2) {        var pow = Math.pow(10, this.scale), number = arg1 * pow + arg2 * pow;        return number / pow;        }    //减法    function substract() {        var i = 0, len = arguments.length, arg2 = 0,            arg1 = this.isNumeric(arguments[0]) && arguments[0] || 0;        if(len > 2) {            arg2 = this.add.apply(this, Array.prototype.slice.call(arguments,1));        } else {            arg2 = this.isNumeric(arguments[1]) && arguments[1] || 0;        }        return _substract.call(this, arg1, arg2);    }    //两个数相减    function _substract(arg1, arg2) {        var pow = Math.pow(10, this.scale), number = arg1 * pow - arg2 * pow;        return number / pow;            }    //乘法    function multiply() {        var i = 0, len = arguments.length, sum = 1,             arg1 = this.isNumeric(arguments[0]) && arguments[0] || 0,            arg2 = this.isNumeric(arguments[1]) && arguments[1] || 0;        sum = _multiply.call(this, arg1, arg2);        if(len > 2) {            sum = _multiply.call(this, sum, this.multiply.apply(this, Array.prototype.slice.call(arguments,2)));        }        return sum;    }    //两个数相乘    function _multiply(arg1, arg2) {        var pow = Math.pow(10, this.scale), number = (arg1 * pow) * (arg2 * pow);        return number / (pow * pow);    }    //除法    function divid() {        var i = 0, len = arguments.length, sum = 1,             arg1 = this.isNumeric(arguments[0]) && arguments[0] || 0,            arg2 = 1;        if(len > 2) {            arg2 = this.multiply.apply(this, Array.prototype.slice.call(arguments,1));        } else {            arg2 = this.isNumeric(arguments[1]) && arguments[1] || arg2;        }        return arg2 && _divid.call(this, arg1, arg2) || 0;          }    //两个数相除    function _divid(arg1, arg2) {        var pow = Math.pow(10, this.scale), number = (arg1 * pow) / (arg2 * pow);        return number ;    }    //设置精度    function _setScale(number, scale, notRound) {        //默认精度为2,因为电价的字段一般都是精度为2        var _scale = scale || this.scale, _pow = Math.pow(10, _scale),             _number = this.isNumeric(number) && number || 0;        if(notRound) {            //将浮点数进行提升为整数            _number = win.parseInt(_number * _pow) / _pow;        }         //toFixed会自动进行四舍五入,如果_number的精度大于_scale时        return Number(_number).toFixed(_scale);     }    //判断是否为数字    function _isNumeric(number) {        var fNaN = win.isNaN(number);        return !fNaN && !!number || fNaN && number != undefined;    }    //两个浮点数比较    function equal(arg1, arg2, scale) {        var _scale = scale || this.scale;        return Number(arg1).toFixed(_scale) === Number(arg2).toFixed(_scale);    }    //接口绑定    win = win || window;    win.Calc = Calc;    return Calc;})(window);

注意

对于Calc.js中的Calc采用的是组件极简定定义法,同时利用工厂方法模式getInstance来创建Calc的实例对象,当然还可以采用function配合prototype来定义组件,但是这种小计算器采用极简定义法更方便些。

原创粉丝点击