index.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. "use strict";
  2. var __spreadArrays = (this && this.__spreadArrays) || function () {
  3. for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
  4. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  5. for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  6. r[k] = a[j];
  7. return r;
  8. };
  9. Object.defineProperty(exports, "__esModule", { value: true });
  10. exports.enableBoundaryChecking = exports.float2Fixed = exports.digitLength = exports.round = exports.divide = exports.times = exports.minus = exports.plus = exports.strip = void 0;
  11. /**
  12. * @desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。
  13. * 问题示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998
  14. */
  15. /**
  16. * 把错误的数据转正
  17. * strip(0.09999999999999998)=0.1
  18. */
  19. function strip(num, precision) {
  20. if (precision === void 0) { precision = 15; }
  21. return +parseFloat(Number(num).toPrecision(precision));
  22. }
  23. exports.strip = strip;
  24. /**
  25. * Return digits length of a number
  26. * @param {*number} num Input number
  27. */
  28. function digitLength(num) {
  29. // Get digit length of e
  30. var eSplit = num.toString().split(/[eE]/);
  31. var len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
  32. return len > 0 ? len : 0;
  33. }
  34. exports.digitLength = digitLength;
  35. /**
  36. * 把小数转成整数,支持科学计数法。如果是小数则放大成整数
  37. * @param {*number} num 输入数
  38. */
  39. function float2Fixed(num) {
  40. if (num.toString().indexOf('e') === -1) {
  41. return Number(num.toString().replace('.', ''));
  42. }
  43. var dLen = digitLength(num);
  44. return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
  45. }
  46. exports.float2Fixed = float2Fixed;
  47. /**
  48. * 检测数字是否越界,如果越界给出提示
  49. * @param {*number} num 输入数
  50. */
  51. function checkBoundary(num) {
  52. if (_boundaryCheckingState) {
  53. if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
  54. console.warn(num + " is beyond boundary when transfer to integer, the results may not be accurate");
  55. }
  56. }
  57. }
  58. /**
  59. * 精确乘法
  60. */
  61. function times(num1, num2) {
  62. var others = [];
  63. for (var _i = 2; _i < arguments.length; _i++) {
  64. others[_i - 2] = arguments[_i];
  65. }
  66. if (others.length > 0) {
  67. return times.apply(void 0, __spreadArrays([times(num1, num2), others[0]], others.slice(1)));
  68. }
  69. var num1Changed = float2Fixed(num1);
  70. var num2Changed = float2Fixed(num2);
  71. var baseNum = digitLength(num1) + digitLength(num2);
  72. var leftValue = num1Changed * num2Changed;
  73. checkBoundary(leftValue);
  74. return leftValue / Math.pow(10, baseNum);
  75. }
  76. exports.times = times;
  77. /**
  78. * 精确加法
  79. */
  80. function plus(num1, num2) {
  81. var others = [];
  82. for (var _i = 2; _i < arguments.length; _i++) {
  83. others[_i - 2] = arguments[_i];
  84. }
  85. if (others.length > 0) {
  86. return plus.apply(void 0, __spreadArrays([plus(num1, num2), others[0]], others.slice(1)));
  87. }
  88. var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
  89. return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
  90. }
  91. exports.plus = plus;
  92. /**
  93. * 精确减法
  94. */
  95. function minus(num1, num2) {
  96. var others = [];
  97. for (var _i = 2; _i < arguments.length; _i++) {
  98. others[_i - 2] = arguments[_i];
  99. }
  100. if (others.length > 0) {
  101. return minus.apply(void 0, __spreadArrays([minus(num1, num2), others[0]], others.slice(1)));
  102. }
  103. var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
  104. return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
  105. }
  106. exports.minus = minus;
  107. /**
  108. * 精确除法
  109. */
  110. function divide(num1, num2) {
  111. var others = [];
  112. for (var _i = 2; _i < arguments.length; _i++) {
  113. others[_i - 2] = arguments[_i];
  114. }
  115. if (others.length > 0) {
  116. return divide.apply(void 0, __spreadArrays([divide(num1, num2), others[0]], others.slice(1)));
  117. }
  118. var num1Changed = float2Fixed(num1);
  119. var num2Changed = float2Fixed(num2);
  120. checkBoundary(num1Changed);
  121. checkBoundary(num2Changed);
  122. // fix: 类似 10 ** -4 为 0.00009999999999999999,strip 修正
  123. return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
  124. }
  125. exports.divide = divide;
  126. /**
  127. * 四舍五入
  128. */
  129. function round(num, ratio) {
  130. var base = Math.pow(10, ratio);
  131. return divide(Math.round(times(num, base)), base);
  132. }
  133. exports.round = round;
  134. var _boundaryCheckingState = true;
  135. /**
  136. * 是否进行边界检查,默认开启
  137. * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
  138. */
  139. function enableBoundaryChecking(flag) {
  140. if (flag === void 0) { flag = true; }
  141. _boundaryCheckingState = flag;
  142. }
  143. exports.enableBoundaryChecking = enableBoundaryChecking;
  144. exports.default = {
  145. strip: strip,
  146. plus: plus,
  147. minus: minus,
  148. times: times,
  149. divide: divide,
  150. round: round,
  151. digitLength: digitLength,
  152. float2Fixed: float2Fixed,
  153. enableBoundaryChecking: enableBoundaryChecking,
  154. };
  155. //# sourceMappingURL=index.js.map