Recently, I was working on a mobile phone numeric keypad, and needed to add and subtract floating-point numbers. However, in the floating-point addition and subtraction method of native JavaScript, 0.1+0.2= 0.30000000000000004 was unexpected, but WHAT I wanted was 0.1+0.2=0.3. On the Internet to find a good library, on their own hands to achieve a floating point number of addition and subtraction function

The principle of analysis

Due to a bug in floating-point calculation, in order to get the result:

  1. To convert a floating-point number to an integer, recording the maximum number of small digits between two numbers, followed by a zero for the smaller number
      100.234 + 0.0005 // Record the maximum number of decimal places is 4
      100.234= = >'100' + '2340' // '234' should be followed by a 0
      0.0005= = >'00005'
    Copy the code
  2. Use parseInt to convert to an integer
      parseInt('100234') / / 1002340
      parseInt('00005') / / 5
      parseInt('100234') + parseInt('00005') = >1002345
    Copy the code
  3. You get the result, you convert it to a string, and then you insert the decimal point
      ' ' + 1002345= >'1002345'
      // According to the recorded decimal position
      '1002345'.slice(-4) + '. ' + '1002345'.slice(0.4) = >'100.2345'
    Copy the code

Code implementation

function add(x, y) { // both x and y are positive or negative
  x = typeof x === 'string' ? x : ' ' + x
  y = typeof y === 'string' ? y : ' ' + y
  let [intX, floatX] = x.split('. ')
  let [intY, floatY] = y.split('. ')
  let floatLengthMax = 0
  let result = ' '
  // Get the largest number of decimals in x and y
  if(floatX && floatY) {
    floatLengthMax = Math.max(floatX.length, floatY.length)
  } else if(floatX === undefined&& floatY ! = =undefined) {
    floatLengthMax = floatY.length
  } else if(floatX ! = =undefined && floatY === undefined) {
    floatLengthMax = floatX.length
  } else {
    floatLengthMax = 0
  }
  // Do different processing depending on whether x and y are decimal numbers
  if(floatX === undefined && floatY === undefined) { // x, y are integers
    return parseInt(intX) + parseInt(intY) + ' '
  } else if(floatX ! = =undefined && floatY === undefined) { // x is a decimal, y is an integer
    result =  parseInt(intX + floatX) + parseInt(intY + floatX.replace(/\d/g.'0')) + ' '
  } else if(floatX === undefined&& floatY ! = =undefined) { // x is an integer, y is a decimal
    result =  parseInt(intX + floatY.replace(/\d/g.'0')) + parseInt(intY + floatY) + ' '
  } else if(floatX ! = =undefined&& floatY ! = =undefined) { // both x and y are decimals
    let stringX = ' '
    let stringY = ' '
    if(floatX.length === floatLengthMax){
      stringX = intX + floatX
      stringY = intY + floatY + floatX.slice(floatY.length).replace(/\d/g.'0')}else {
      stringX = intX + floatX + floatY.slice(floatX.length).replace(/\d/g.'0')
      stringY = intY + floatY
    }
    result = parseInt(stringX) + parseInt(stringY) + ' '
  }
  // Determine whether the result needs to be added by 0
  For example, 0.0003 + 0.00002 =>.32
  if(result.length <= floatLengthMax) {
    let zeroStr = ' '
    for(let i = 0; i < floatLengthMax - result.length; i++) {
      zeroStr += '0'
    }
    return '0. + zeroStr + result
  } else {
    return result.slice(0, -floatLengthMax) + '. ' + result.slice(-floatLengthMax)      
  }
}

function sub(x, y) { // one of x and y is negative
  x = typeof x === 'string' ? x : ' ' + x
  y = typeof y === 'string' ? y : ' ' + y
  let [intX, floatX] = x.split('. ')
  let [intY, floatY] = y.split('. ')
  let result = ' '
  // Get the largest number of decimals in x and y
  if(floatX && floatY) {
    floatLengthMax = Math.max(floatX.length, floatY.length)
  } else if(floatX === undefined&& floatY ! = =undefined) {
    floatLengthMax = floatY.length
  } else if(floatX ! = =undefined && floatY === undefined) {
    floatLengthMax = floatX.length
  } else {
    floatLengthMax = 0
  }
  // Do different processing depending on whether x and y are decimal numbers
  if(floatX === undefined && floatY === undefined) { // x, y are integers
    return parseInt(intX) + parseInt(intY) + ' '
  } else if(floatX ! = =undefined && floatY === undefined) { // x is a decimal, y is an integer
    result = parseInt(intX + floatX) + parseInt(intY + floatX.replace(/\d/g.'0')) + ' '
  } else if(floatX === undefined&& floatY ! = =undefined) { // x is an integer, y is a decimal
    result =  parseInt(intX + floatY.replace(/\d/g.'0')) + parseInt(intY + floatY) + ' '
  } else if(floatX ! = =undefined&& floatY ! = =undefined) { // both x and y are decimals
    let stringX = ' '
    let stringY = ' '
    if(floatX.length === floatLengthMax){
      stringX = intX + floatX
      stringY = intY + floatY + floatX.slice(floatY.length).replace(/\d/g.'0')}else {
      stringX = intX + floatX + floatY.slice(floatX.length).replace(/\d/g.'0')
      stringY = intY + floatY
    }
    result = parseInt(stringX) + parseInt(stringY) + ' '
  }

  // Determine whether the result needs to be added by 0
  // For example, 0.0003-0.00002 =>.-28
  let minus = result.indexOf(The '-') > -1 ? The '-' : ' '
  result = result.indexOf(The '-') > -1 ? result.slice(1) : result
  if(result.length <= floatLengthMax) {
    let zeroStr = ' '
    for(let i = 0; i < floatLengthMax - result.length; i++) {
      zeroStr += '0'
    }
    return minus + '0. + zeroStr + result
  } else {
    return minus + result.slice(0, -floatLengthMax) + '. ' + result.slice(-floatLengthMax)
  }
}

function calcFloat(x, y) {
  let valueX = typeof x === 'string' ? parseFloat(x) : x
  let valueY = typeof y === 'string' ? parseFloat(y) : y
  if(x >= 0 && y >= 0) {
    return add(x, y)
  } else if(x < 0 && y >= 0) {return sub(y, x)
  } else if(x >= 0 && y < 0) {
    return sub(x, y)
  } else {
    return add(x, y)
  }
} 
Copy the code