js计算器组件Calc.js
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;js arguments
win.Calc = Calc;
return Calc;
})(window);
注意
对于Calc.js中的Calc采⽤的是组件极简定定义法,同时利⽤⼯⼚⽅法模式getInstance来创建Calc的实例对象,当然还可以采⽤function配合prototype来定义组件,但是这种⼩计算器采⽤极简定义法更⽅便些。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。