/ / operation of encapsulation, solve the problem of js accuracy loss/reference/www.cnblogs.com/snandy/p/49…


/** * $operator contains five methods, including addition, subtraction, multiplication, and division, and toFixed, to ensure that floating-point operations do not lose precision ** We know that floating point calculations in computer programming languages have precision loss (or rounding error), The root cause is binary and implement the bit limit some numbers can not be finite representation * the following is the decimal corresponding binary representation * 0.1 >> 0.0001 1001 1001 1001... (1001 infinite loop) * 0.2 >> 0.0011 0011 0011 0011 0011... (0011 Infinite loop) * Computers store each data type with a finite width. For example, JavaScript uses 64 bits to store numeric types, so anything beyond that will be discarded. The missing part is the missing part. ** ** method ** * add/subtract/multiply /divide/toFixed ** ** explame ** * 0.1 + 0.2 == 0.30000000000000004 0.00000000000004) * 0.2 + 0.4 == 0.6000000000000001 (more than 0.0000000000001) * 19.9 * 100 == 1989.9999999999998 (less ToFixed (2) // 1.33 is not 1.34 * * $operator.add(0.1, 0.2) >> 0.3 * $operator.multiply(19.9, 100) >> 1990 * $operator. ToFixed (1.335, 2) >> 1.34 * */
/* * check whether obj is an integer */
const isInteger = (obj) = > Math.floor(obj) === obj

/* * Converts a floating point number to an integer, returning integer and multiple. For example, 3.14 >> 314, the multiple is 100 * @param floatNum {number} decimal * @return {object} * {times:100, num: 314} */
const toInteger = (floatNum) = > {
  var res = { times: 1.num: 0 }
  var isNegative = floatNum < 0
  if (isInteger(floatNum)) {
    res.num = floatNum
    return res
  }
  var strfi  = floatNum + ' '
  var dotPos = strfi.indexOf('. ')
  var len    = strfi.substr(dotPos+1).length
  var times  = Math.pow(10, len)
  var intNum = parseInt(Math.abs(floatNum) * times + 0.5.10)
  res.times  = times
  if (isNegative) {
    intNum = -intNum
  }
  res.num = intNum
  return res
}
/* * Core method to achieve addition, subtraction, multiplication and division operations, to ensure no loss of precision * * * @param a {number} 1 * @param b {number} 2 * @param digits {number} Such as 2, which would hold to two decimal places * @ param op {string} operation type, there are subtracting (add/subtract/multiply/divide) * * /
function operation(a, b, digits, op) {
  var o1 = toInteger(a)
  var o2 = toInteger(b)
  var n1 = o1.num
  var n2 = o2.num
  var t1 = o1.times
  var t2 = o2.times
  var max = t1 > t2 ? t1 : t2
  var result = null
  switch (op) {
    / / add
    case 'add':
      if (t1 === t2) { // The two decimal places are the same
        result = n1 + n2
      } else if (t1 > t2) { // O1 is greater than O2
        result = n1 + n2 * (t1 / t2)
      } else { // O1 is less than O2
        result = n1 * (t2 / t1) + n2
      }
      return result / max
    case 'subtract':
      if (t1 === t2) {
        result = n1 - n2
      } else if (t1 > t2) {
        result = n1 - n2 * (t1 / t2)
      } else {
        result = n1 * (t2 / t1) - n2
      }
      return result / max
    case 'multiply':
      return (n1 * n2) / (t1 * t2)
    case 'divide':
      return (n1 / n2) * (t2 / t1)
  }
}

function add(a, b, digits) {
  return operation(a, b, digits, 'add')}function subtract(a, b, digits) {
  return operation(a, b, digits, 'subtract')}function multiply(a, b, digits) {
  return operation(a, b, digits, 'multiply')}function divide(a, b, digits) {
  return operation(a, b, digits, 'divide')}function toFixed(num, s) {
  var times = Math.pow(10, s)
  var des = num * times + 0.5
  des = parseInt(des, 10) / times
  return des + ' '
}


export const $operator =  {
  add,
  subtract, 
  multiply,
  divide,
  toFixed
}
Copy the code