UNPKG

native-class-ext

Version:

js原生对象增加常用方法

182 lines (170 loc) 4.86 kB
(function(){ const defineProperty = require('./defineProperty.js') /** * 对Number类进行扩展 * @author gwl * @since 2020年5月8日13:04:41 * js进行计算时有时会出现小数点导致计算错误,如 * 0.1+0.2=0.30000000000000004 * 0.3-0.2=0.09999999999999998 * 0.1*3=0.30000000000000004 * 2.4/0.8=2.9999999999999996 * 解决方法:转成整数计算 * */ function init(){ /** * 加 * @param {Number} augend 被加数 * @return this+augend * */ defineProperty(Number.prototype, '$add', add) /** * 减 * @param {Number} subtrahend 被减数 * @return this-subtrahend * */ defineProperty(Number.prototype, '$subtract', subtract) /** * 乘 * @param {Number} multiplicand 乘数 * @return this*multiplicand * */ defineProperty(Number.prototype, '$multiply', multiply) /** * 除 * @param {Number} divisor * @param {Number} scale 保留小数位数 * @param {Number} roundingMode 舍入方式 * @return this/multiplicand * */ defineProperty(Number.prototype, '$divide', divide) /** * 设置精度 * @param {Number} scale 小数位数,默认2 * @param {Number} roundingMode 舍入方式,默认Number.$ROUND_HALF_UP * */ defineProperty(Number.prototype, '$setScale', setScale) } /** 进位, 1.01->1.1、-1.01->-1.1 */ defineProperty(Number, '$ROUND_UP', 0) /** 舍弃, 1.01->1.0、-1.01->-1.0 */ defineProperty(Number, '$ROUND_DOWN', 1) /** 常规四舍五入 */ defineProperty(Number, '$ROUND_HALF_UP', 4) function add(augend){ const [num1, num2] = getEqScale(this, augend); const res = parseInt(num1.numStr) + parseInt(num2.numStr); return addPoint(res, num1.scale); } function subtract(subtrahend){ const [num1, num2] = getEqScale(this, subtrahend); const res = parseInt(num1.numStr) - parseInt(num2.numStr); return addPoint(res, num1.scale); } function multiply(multiplicand){ const num1 = getNumberInfo(this); const num2 = getNumberInfo(multiplicand); let res = parseInt(num1.numStr) * parseInt(num2.numStr); return addPoint(res, num1.scale + num2.scale); } function divide(divisor, scale=2, roundingMode=Number.$ROUND_HALF_UP){ const [num1, num2] = getEqScale(this, divisor); let res = parseInt(num1.numStr) / parseInt(num2.numStr); return res.$setScale(scale, roundingMode); } function setScale(scale=2, roundingMode=Number.$ROUND_HALF_UP){ let no, res; switch(roundingMode){ //常规四舍五入 case Number.$ROUND_HALF_UP: return parseFloat(this.toFixed(scale)); //舍弃 case Number.$ROUND_DOWN: ni = getNumberInfo(this); if(ni.scale == 0) return this; res = ni.numSplit[0] + '.' + ni.numSplit[1].slice(0, scale); return parseFloat(res); //进位 case Number.$ROUND_UP: ni = getNumberInfo(this); if(ni.scale == 0) return this; let scaleAfter = ni.numSplit[1].slice(scale);//, scale+1 if(scaleAfter) scaleAfter = parseInt(scaleAfter); res = parseInt(ni.numSplit[0] + ni.numSplit[1].slice(0, scale)); if(scaleAfter>0) { if(this>0) res++; else if(this<0) res--; } return addPoint(res, scale); } } /** * 去小数点,并保证小数点移动位数相同 * */ function getEqScale(num1, num2){ num1 = getNumberInfo(num1); num2 = getNumberInfo(num2); const masScale = Math.max(num1.scale, num2.scale); addZeroEnd(num1, masScale); addZeroEnd(num2, masScale); return [num1, num2]; } /** * 解析数字信息 * @return {Object} * num {Number} 原数字 * numSplit {Array} 根据小数点拆成数组 * scale {Number} 小数点后位数 * numStr {String} 去小数点后字符串 * */ function getNumberInfo(num){ let numStr = num.toString(); const numSplit = numStr.split("."); let scale = 0; if(numSplit.length===2) { scale = numSplit[1].length; numStr = numSplit[0] + numSplit[1]; } return { num, numSplit, scale, numStr }; } /** * 在尾部添加0 * */ function addZeroEnd(numInfo, scale){ const offset = scale-numInfo.scale ; if(offset > 0){ numInfo.scale = scale; numInfo.numStr = numInfo.numStr + '0'.padEnd(offset, '0'); } } //添加小数点, addPoint(123, 2) = 1.23 function addPoint(num, scale=0){ if(scale === 0){ return num; } let isMinus = false if(num < 0) { isMinus = true num = Math.abs(num) } let str = num.toString().padStart(scale, '0'); let res = str.slice(0, -scale); if(!res){ res = '0'; } let temp = str.slice(-scale); if(temp){ res += '.' + temp; } res = parseFloat(res); if(isMinus) { res = 0-res } return res; } init(); })()