{"version":3,"file":"digit.js","sources":["../../../../../src/sheep/helper/digit.js"],"sourcesContent":["let _boundaryCheckingState = true // 是否进行越界检查的全局开关\r\n\r\n/**\r\n * 把错误的数据转正\r\n * @private\r\n * @example strip(0.09999999999999998)=0.1\r\n */\r\nfunction strip(num, precision = 15) {\r\n return +parseFloat(Number(num).toPrecision(precision))\r\n}\r\n\r\n/**\r\n * Return digits length of a number\r\n * @private\r\n * @param {*number} num Input number\r\n */\r\nfunction digitLength(num) {\r\n // Get digit length of e\r\n const eSplit = num.toString().split(/[eE]/)\r\n const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0)\r\n return len > 0 ? len : 0\r\n}\r\n\r\n/**\r\n * 把小数转成整数,如果是小数则放大成整数\r\n * @private\r\n * @param {*number} num 输入数\r\n */\r\nfunction float2Fixed(num) {\r\n if (num.toString().indexOf('e') === -1) {\r\n return Number(num.toString().replace('.', ''))\r\n }\r\n const dLen = digitLength(num)\r\n return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num)\r\n}\r\n\r\n/**\r\n * 检测数字是否越界,如果越界给出提示\r\n * @private\r\n * @param {*number} num 输入数\r\n */\r\nfunction checkBoundary(num) {\r\n if (_boundaryCheckingState) {\r\n if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {\r\n console.warn(`${num} 超出了精度限制,结果可能不正确`)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 把递归操作扁平迭代化\r\n * @param {number[]} arr 要操作的数字数组\r\n * @param {function} operation 迭代操作\r\n * @private\r\n */\r\nfunction iteratorOperation(arr, operation) {\r\n const [num1, num2, ...others] = arr\r\n let res = operation(num1, num2)\r\n\r\n others.forEach((num) => {\r\n res = operation(res, num)\r\n })\r\n\r\n return res\r\n}\r\n\r\n/**\r\n * 高精度乘法\r\n * @export\r\n */\r\nexport function times(...nums) {\r\n if (nums.length > 2) {\r\n return iteratorOperation(nums, times)\r\n }\r\n\r\n const [num1, num2] = nums\r\n const num1Changed = float2Fixed(num1)\r\n const num2Changed = float2Fixed(num2)\r\n const baseNum = digitLength(num1) + digitLength(num2)\r\n const leftValue = num1Changed * num2Changed\r\n\r\n checkBoundary(leftValue)\r\n\r\n return leftValue / Math.pow(10, baseNum)\r\n}\r\n\r\n/**\r\n * 高精度加法\r\n * @export\r\n */\r\nexport function plus(...nums) {\r\n if (nums.length > 2) {\r\n return iteratorOperation(nums, plus)\r\n }\r\n\r\n const [num1, num2] = nums\r\n // 取最大的小数位\r\n const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)))\r\n // 把小数都转为整数然后再计算\r\n return (times(num1, baseNum) + times(num2, baseNum)) / baseNum\r\n}\r\n\r\n/**\r\n * 高精度减法\r\n * @export\r\n */\r\nexport function minus(...nums) {\r\n if (nums.length > 2) {\r\n return iteratorOperation(nums, minus)\r\n }\r\n\r\n const [num1, num2] = nums\r\n const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)))\r\n return (times(num1, baseNum) - times(num2, baseNum)) / baseNum\r\n}\r\n\r\n/**\r\n * 高精度除法\r\n * @export\r\n */\r\nexport function divide(...nums) {\r\n if (nums.length > 2) {\r\n return iteratorOperation(nums, divide)\r\n }\r\n\r\n const [num1, num2] = nums\r\n const num1Changed = float2Fixed(num1)\r\n const num2Changed = float2Fixed(num2)\r\n checkBoundary(num1Changed)\r\n checkBoundary(num2Changed)\r\n // 重要,这里必须用strip进行修正\r\n return times(\r\n num1Changed / num2Changed,\r\n strip(Math.pow(10, digitLength(num2) - digitLength(num1))),\r\n )\r\n}\r\n\r\n/**\r\n * 四舍五入\r\n * @export\r\n */\r\nexport function round(num, ratio) {\r\n const base = Math.pow(10, ratio)\r\n let result = divide(Math.round(Math.abs(times(num, base))), base)\r\n if (num < 0 && result !== 0) {\r\n result = times(result, -1)\r\n }\r\n // 位数不足则补0\r\n return result\r\n}\r\n\r\n/**\r\n * 是否进行边界检查,默认开启\r\n * @param flag 标记开关,true 为开启,false 为关闭,默认为 true\r\n * @export\r\n */\r\nexport function enableBoundaryChecking(flag = true) {\r\n _boundaryCheckingState = flag\r\n}\r\n\r\nexport default {\r\n times,\r\n plus,\r\n minus,\r\n divide,\r\n round,\r\n enableBoundaryChecking,\r\n}\r\n"],"names":[],"mappings":";AAOA,SAAS,MAAM,KAAK,YAAY,IAAI;AAClC,SAAO,CAAC,WAAW,OAAO,GAAG,EAAE,YAAY,SAAS,CAAC;AACvD;AAOA,SAAS,YAAY,KAAK;AAExB,QAAM,SAAS,IAAI,SAAQ,EAAG,MAAM,MAAM;AAC1C,QAAM,OAAO,OAAO,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,SAAS,EAAE,OAAO,CAAC,KAAK;AACpE,SAAO,MAAM,IAAI,MAAM;AACzB;AAOA,SAAS,YAAY,KAAK;AACxB,MAAI,IAAI,SAAU,EAAC,QAAQ,GAAG,MAAM,IAAI;AACtC,WAAO,OAAO,IAAI,SAAQ,EAAG,QAAQ,KAAK,EAAE,CAAC;AAAA,EAC9C;AACD,QAAM,OAAO,YAAY,GAAG;AAC5B,SAAO,OAAO,IAAI,MAAM,OAAO,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,OAAO,GAAG;AACxE;AAOA,SAAS,cAAc,KAAK;AACE;AAC1B,QAAI,MAAM,OAAO,oBAAoB,MAAM,OAAO,kBAAkB;AAClE,cAAQ,KAAK,GAAG,GAAG,kBAAkB;AAAA,IACtC;AAAA,EACF;AACH;AAQA,SAAS,kBAAkB,KAAK,WAAW;AACzC,QAAM,CAAC,MAAM,MAAM,GAAG,MAAM,IAAI;AAChC,MAAI,MAAM,UAAU,MAAM,IAAI;AAE9B,SAAO,QAAQ,CAAC,QAAQ;AACtB,UAAM,UAAU,KAAK,GAAG;AAAA,EAC5B,CAAG;AAED,SAAO;AACT;AAMO,SAAS,SAAS,MAAM;AAC7B,MAAI,KAAK,SAAS,GAAG;AACnB,WAAO,kBAAkB,MAAM,KAAK;AAAA,EACrC;AAED,QAAM,CAAC,MAAM,IAAI,IAAI;AACrB,QAAM,cAAc,YAAY,IAAI;AACpC,QAAM,cAAc,YAAY,IAAI;AACpC,QAAM,UAAU,YAAY,IAAI,IAAI,YAAY,IAAI;AACpD,QAAM,YAAY,cAAc;AAEhC,gBAAc,SAAS;AAEvB,SAAO,YAAY,KAAK,IAAI,IAAI,OAAO;AACzC;AAoCO,SAAS,UAAU,MAAM;AAC9B,MAAI,KAAK,SAAS,GAAG;AACnB,WAAO,kBAAkB,MAAM,MAAM;AAAA,EACtC;AAED,QAAM,CAAC,MAAM,IAAI,IAAI;AACrB,QAAM,cAAc,YAAY,IAAI;AACpC,QAAM,cAAc,YAAY,IAAI;AACpC,gBAAc,WAAW;AACzB,gBAAc,WAAW;AAEzB,SAAO;AAAA,IACL,cAAc;AAAA,IACd,MAAM,KAAK,IAAI,IAAI,YAAY,IAAI,IAAI,YAAY,IAAI,CAAC,CAAC;AAAA,EAC1D;AACH;AAMO,SAAS,MAAM,KAAK,OAAO;AAChC,QAAM,OAAO,KAAK,IAAI,IAAI,KAAK;AAC/B,MAAI,SAAS,OAAO,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI;AAChE,MAAI,MAAM,KAAK,WAAW,GAAG;AAC3B,aAAS,MAAM,QAAQ,EAAE;AAAA,EAC1B;AAED,SAAO;AACT;;"}