Mantissa Addition

JavaScript performance comparison

Test case created by venkatloganathan

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  const EMPTY_STRING = '';
  const MULTIPLIER_FACTOR_CORRECTION =100;
  const NEGATIVE_SYMBOL_STRING = '-';
  
  const SUFFIX_ZERO_01     = '0';
  const SUFFIX_ZERO_02     = '00';
  const SUFFIX_ZERO_03     = '000';
  const SUFFIX_ZERO_04     = '0000';
  const SUFFIX_ZERO_05     = '00000';
  const SUFFIX_ZERO_06     = '000000';
  const SUFFIX_ZERO_07     = '0000000';
  const SUFFIX_ZERO_08     = '00000000';
  const SUFFIX_ZERO_09     = '000000000';
  const SUFFIX_ZERO_10     = '0000000000';
  const SUFFIX_ZERO_11     = '00000000000';
  const SUFFIX_ZERO_12     = '000000000000';
  const SUFFIX_ZERO_13     = '0000000000000';
  const SUFFIX_ZERO_14     = '00000000000000';
  const SUFFIX_ZERO_15     = '000000000000000';
  const SUFFIX_ZERO_16     = '0000000000000000';
  const SUFFIX_ZERO_17     = '00000000000000000';
  const SUFFIX_ZERO_18     = '000000000000000000';
  const SUFFIX_ZERO_19     = '0000000000000000000';
  const SUFFIX_ZERO_20     = '00000000000000000000';
  
    const DECIMAL_NOTATION = '.';
    const DECIMAL_NOTATION_LENGTH = DECIMAL_NOTATION.length;
  
    const PREFIX_ZERO_00 = '0.';
    const PREFIX_ZERO_01 = '0.0';
    const PREFIX_ZERO_02 = '0.00';
    const PREFIX_ZERO_03 = '0.000';
    const PREFIX_ZERO_04 = '0.0000';
    const PREFIX_ZERO_05 = '0.00000';
    const PREFIX_ZERO_06 = '0.000000';
    const PREFIX_ZERO_07 = '0.0000000';
    const PREFIX_ZERO_08 = '0.00000000';
    const PREFIX_ZERO_09 = '0.000000000';
    const PREFIX_ZERO_10 = '0.0000000000';
    const PREFIX_ZERO_11 = '0.00000000000';
    const PREFIX_ZERO_12 = '0.000000000000';
    const PREFIX_ZERO_13 = '0.0000000000000';
    const PREFIX_ZERO_14 = '0.00000000000000';
    const PREFIX_ZERO_15 = '0.000000000000000';
    const PREFIX_ZERO_16 = '0.0000000000000000';
    const PREFIX_ZERO_17 = '0.00000000000000000';
    const PREFIX_ZERO_18 = '0.000000000000000000';
    const PREFIX_ZERO_19 = '0.0000000000000000000';
    const PREFIX_ZERO_20 = '0.00000000000000000000';
  
  function naturalMultiply(operand1, naturalLogDecimals)
    {
     const isOperandNegative = operand1 < 0;
      let useNegative = isOperandNegative;
  
      if (naturalLogDecimals < 0)
      {
        useNegative = !useNegative;
        naturalLogDecimals *= -1;
      }
  
      const operandAsString = operand1.toString();
  
      let operand = isOperandNegative ? operandAsString.substr(1) : operandAsString;
  
      const decimalPosition = operand.indexOf('.');
      const operandLength = operand.length;
      let result = '';
      let decimalsLength = 0;
      if (decimalPosition > 0)
      {
        result = operand.substr(0, decimalPosition);
        decimalsLength = operandLength - decimalPosition - 1;
        result += operand.substr(decimalPosition + 1, naturalLogDecimals);
      }
      else
      {
        result = operand.substr(0);
      }
  
      const excessDigits = decimalsLength - naturalLogDecimals;
      if (excessDigits > 0)
      {
        result += DECIMAL_NOTATION;
        let decimalIndex = decimalPosition + 1 + naturalLogDecimals;
        result += operand.substr(decimalIndex);
      }
      else if (excessDigits < 0)
      {
        let excess = Math.abs(excessDigits);
        switch (excess)
        {
          case 1:
            result += SUFFIX_ZERO_01;
            break;
          case 2:
            result += SUFFIX_ZERO_02;
            break;
          case 3:
            result += SUFFIX_ZERO_03;
            break;
          case 4:
            result += SUFFIX_ZERO_04;
            break;
          case 5:
            result += SUFFIX_ZERO_05;
            break;
          case 6:
            result += SUFFIX_ZERO_06;
            break;
          case 7:
            result += SUFFIX_ZERO_07;
            break;
          case 8:
            result += SUFFIX_ZERO_08;
            break;
          case 9:
            result += SUFFIX_ZERO_09;
            break;
          case 10:
            result += SUFFIX_ZERO_10;
            break;
          case 11:
            result += SUFFIX_ZERO_11;
            break;
          case 12:
            result += SUFFIX_ZERO_12;
            break;
          case 13:
            result += SUFFIX_ZERO_13;
            break;
          case 14:
            result += SUFFIX_ZERO_14;
            break;
          case 15:
            result += SUFFIX_ZERO_15;
            break;
          case 16:
            result += SUFFIX_ZERO_16;
            break;
          case 17:
            result += SUFFIX_ZERO_17;
            break;
          case 18:
            result += SUFFIX_ZERO_18;
            break;
          case 19:
            result += SUFFIX_ZERO_19;
            break;
          case 20:
            result += SUFFIX_ZERO_20;
            break;
        }
      }
      if (useNegative)
      {
        result = '-' + result;
      }
      return Number(result);  }
  
  function getExcessDigits(excessDigits) {
  let result = '';
        const excess = Math.abs(excessDigits);
  switch(excess) {
    case 1:
  result = SUFFIX_ZERO_1;
  break;
  case 2:
  result = SUFFIX_ZERO_2;
  break;
  case 3:
  result = SUFFIX_ZERO_3;
  break;
  case 4:
  result = SUFFIX_ZERO_4;
  break;
  case 5:
  result = SUFFIX_ZERO_5;
  break;
  case 6:
  result = SUFFIX_ZERO_6;
  break;
  case 7:
  result = SUFFIX_ZERO_7;
  break;
  case 8:
  result = SUFFIX_ZERO_8;
  break
  case 9:
  result = SUFFIX_ZERO_9;
  break;
  case 10:
  result = SUFFIX_ZERO_10;
  break;
  case 11:
  result = SUFFIX_ZERO_11;
  break;
  case 12:
  result = SUFFIX_ZERO_12;
  break;
  case 13:
  result = SUFFIX_ZERO_13;
  break;
  case 14:
  result = SUFFIX_ZERO_14;
  break;
  case 15:
  result = SUFFIX_ZERO_15;
  break;
  case 16:
  result = SUFFIX_ZERO_16;
  break;
  case 17:
  result = SUFFIX_ZERO_17;
  break;
  case 18:
  result = SUFFIX_ZERO_18;
  break;
  case 19:
  result = SUFFIX_ZERO_19;
  break;
  case 20:
  result = SUFFIX_ZERO_20;
  break;
  }
  return result;
  }
  
    function multiply(num1, num2)
    {
      var factor1 = multiplier(num1) * MULTIPLIER_FACTOR_CORRECTION;
      var factor2 = multiplier(num2) * MULTIPLIER_FACTOR_CORRECTION;
      var multiplier1 = num1 < 0 ? -1 : 1;
      var multiplier2 = num2 < 0 ? -1 : 1;
  
      return (Math.round(Math.abs(num1) * factor1) * Math.round(Math.abs(num2) * factor2) * multiplier1 * multiplier2) / (factor1 * factor2);
    }
    function multiplier(x)
    {
      if (x === undefined || x === null)
      {
        return NaN;
      }
  
      return Math.pow(10, decimalPoints(x));
    }
  
    function decimalPoints(num)
    {
      var numString = String(num);
  
      if (numString.indexOf('e') !== -1)
      {
        var match = numString.match(/([\d.]+)e(-?\+?)(\d+)/);
  
        if (match)
        {
          var decimalPlaces = decimalPoints(match[1]) - (match[2] === '+' ? match[3] : -match[3]);
  
          return decimalPlaces < 0 ? 0 : decimalPlaces;
        }
  
        return 0;
      }
  
      var i = numString.indexOf('.');
  
      if (i === -1)
      {
        return 0;
      }
  
      return numString.length - i - 1;
    }
  
  function getDecimalIndex(operand) {
  const decimalNotationIndex = operand.indexOf(DECIMAL_NOTATION);
      return decimalNotationIndex < 0 ? 0 : decimalNotationIndex;
  }
  
  function getMantissa(operand, mantissaDecimalIndex)
    {
      if (mantissaDecimalIndex === 0)
      {
        return 0;
      }
      const operandLength = operand.length;
      return operandLength - mantissaDecimalIndex - DECIMAL_NOTATION_LENGTH;
    }
  
  function mantissaMultiply(operand1, operand2)
    {
      const isOperandNegative = operand1 < 0;
      let useNegative = isOperandNegative;
  
      const operand1String = operand1.toString();
      const originalOperand1AsString = isOperandNegative ? operand1String.substr(1) : operand1String;
  
      const operand2String = operand2.toString();
      let originalOperand2AsString = operand2String.toString();
      if (operand2 < 0)
      {
        originalOperand2AsString = operand2String.substr(1);
        useNegative = !useNegative;
      }
  
      const mantissaForOperand1 = getDecimalIndex(originalOperand1AsString);
      const mantissaForOperand2 = getDecimalIndex(originalOperand2AsString);
  
      const mantissa = getMantissa(originalOperand1AsString, mantissaForOperand1) + getMantissa(originalOperand2AsString, mantissaForOperand2);
  
      if (mantissa === 0)
      {
        return operand1 * operand2;
      }
  
      let operand1AsString = mantissaForOperand1 <= 0 ? originalOperand1AsString :
        originalOperand1AsString.substr(0, mantissaForOperand1) + originalOperand1AsString.substr(mantissaForOperand1 + 1);
  
      let operand2AsString = mantissaForOperand2 <= 0 ? originalOperand2AsString :
        originalOperand2AsString.substr(0, mantissaForOperand2) + originalOperand2AsString.substr(mantissaForOperand2 + 1);
  
      const manipulatedOperand1 = Number(operand1AsString);
      const manipulatedOperand2 = Number(operand2AsString);
  
      const mantissaResult = manipulatedOperand1 * manipulatedOperand2;
  
  
      return convertMantissaToNumber(mantissaResult.toString(), mantissa, useNegative);
    }
  function convertMantissaToNumber(operand, mantissa, useNegative)
    {
      const operandAsString = operand.toString();
      const originalOperandAsStringLength = operandAsString.length;
      let resultAsString = EMPTY_STRING;
      if (originalOperandAsStringLength > mantissa)
      {
        const decimalIndex = originalOperandAsStringLength - mantissa;
        resultAsString = operandAsString.substr(0, decimalIndex);
        resultAsString += DECIMAL_NOTATION;
        resultAsString += operandAsString.substr(decimalIndex);
      }
      else
      {
        const remaining = mantissa - originalOperandAsStringLength;
        switch (remaining)
        {
          case 0:
            resultAsString = PREFIX_ZERO_00;
            break;
          case 1:
            resultAsString = PREFIX_ZERO_01;
            break;
          case 2:
            resultAsString = PREFIX_ZERO_02;
            break;
          case 3:
            resultAsString = PREFIX_ZERO_03;
            break;
          case 4:
            resultAsString = PREFIX_ZERO_04;
            break;
          case 5:
            resultAsString = PREFIX_ZERO_05;
            break;
          case 6:
            resultAsString = PREFIX_ZERO_06;
            break;
          case 7:
            resultAsString = PREFIX_ZERO_07;
            break;
          case 8:
            resultAsString = PREFIX_ZERO_08;
            break;
          case 9:
            resultAsString = PREFIX_ZERO_09;
            break;
          case 10:
            resultAsString = PREFIX_ZERO_10;
            break;
          case 11:
            resultAsString = PREFIX_ZERO_11;
            break;
          case 12:
            resultAsString = PREFIX_ZERO_12;
            break;
          case 13:
            resultAsString = PREFIX_ZERO_13;
            break;
          case 14:
            resultAsString = PREFIX_ZERO_14;
            break;
          case 15:
            resultAsString = PREFIX_ZERO_15;
            break;
          case 16:
            resultAsString = PREFIX_ZERO_16;
            break;
          case 17:
            resultAsString = PREFIX_ZERO_17;
            break;
          case 18:
            resultAsString = PREFIX_ZERO_18;
            break;
          case 19:
            resultAsString = PREFIX_ZERO_19;
            break;
          case 20:
            resultAsString = PREFIX_ZERO_20;
            break;
        }
        resultAsString += operandAsString;
      }
      if (useNegative)
      {
        resultAsString = NEGATIVE_SYMBOL_STRING + resultAsString;
      }
      return Number(resultAsString);
    };
  
    function add(num1, num2)
    {
      var factor1 = multiplier(num1);
      var factor2 = multiplier(num2);
      var multiplier1 = num1 < 0 ? -1 : 1;
      var multiplier2 = num2 < 0 ? -1 : 1;
  
      return ((Math.round(Math.abs(num1) * factor1 * factor2) * multiplier1) + (Math.round(Math.abs(num2) * factor1 * factor2) * multiplier2)) / (factor1 * factor2);
    }
  
  function mantissaAdd(operand1, operand2)
    {
  let mantissaDifference = 0;
  
  let operand1Difference = 1;
  let operand2Difference = 1;
  
  let isOperand1Negative = false;
  let isOperand2Negative = false;
  
  let originalOperand1AsString = operand1.toString();
  
  if(operand1 < 0) {
  isOperand1Negative = true;
  operand1Difference = -1;
  //originalOperand1AsString  = originalOperand1AsString.substr(1)
  }
  
  let originalOperand2AsString = operand2.toString();
  
  if(operand2 < 0) {
  isOperand2Negative = true;
  operand2Difference = -1;
  //originalOperand2AsString = originalOperand2AsString .substr(1)
  }
  
  const mantissaIndexForOperand1 = getDecimalIndex(originalOperand1AsString);
  const mantissaIndexForOperand2 = getDecimalIndex(originalOperand2AsString);
  
  
      let mantissa = getMantissa(originalOperand1AsString, mantissaIndexForOperand1);
      const mantissaForOperand2 = getMantissa(originalOperand2AsString, mantissaIndexForOperand2);
  
  /*    
  if (mantissa === 0 && mantissaForOperand2 === 0)
      {
        return operand1 + operand2;
      }
  */
  let i = 0;
  let operand1AsString = originalOperand1AsString;
  /*
  if(mantissaIndexForOperand1 > 0) {
  operand1AsString  = '';
  var len = originalOperand1AsString.length
  for(i = 0;  i < len; i++) {
  if(i === mantissaIndexForOperand1) {
  continue;
  }
  operand1AsString  = originalOperand1AsString.charAt(i);
  }
  }
  */
  
  let operand2AsString = originalOperand2AsString;
  
  /*
  if(mantissaIndexForOperand2 > 0) {
  
  operand2AsString = '';
  var len = originalOperand2AsString.length
  for(i = 0;  i < len; i++) {
  if(i === mantissaIndexForOperand2) {
  continue;
  }
  operand2AsString = originalOperand2AsString.charAt(i);
  }
  }
  */
  
      if (mantissaForOperand2 > mantissa)
      {
        mantissaDifference = mantissaForOperand2 - mantissa;
        mantissa = mantissaForOperand2;
        operand1Difference *= Math.pow(10, mantissaDifference);
      }
      else 
      {
        mantissaDifference = mantissa - mantissaForOperand2;
        operand2Difference *= Math.pow(10, mantissaDifference);
      }
  
  let manipulatedOperand1 = Number(operand1AsString) * operand1Difference ;
  let manipulatedOperand2 = Number(operand2AsString) * operand2Difference ;
  
   const mantissaResult = manipulatedOperand1 + manipulatedOperand2;
      //let mantissaResultAsString = mantissaResult.toString();
  return;
  
      let mantissaResultNegative = false;
      if (mantissaResult < 0)
      {
        mantissaResultNegative = true;
        mantissaResultAsString = mantissaResultAsString.substr(1);
      }
  
   return convertMantissaToNumber(mantissaResultAsString, mantissa, mantissaResultNegative );
  
  }

};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Number based Addition
add(1280.24534, 0.0004);
add(0.0004, 1280.24534);
add(0.11111, 1280.24534);
add(0.01, 0.05);
add(0.06, 0.01);
add(100, -10);
add(-137.2342233, -10);
add(-137.2342233, 10);
pending…
Mantissa based Addition
mantissaAdd(1280.24534, 0.0004);
mantissaAdd(0.0004, 1280.24534);
mantissaAdd(0.11111, 1280.24534);
mantissaAdd(0.01, 0.05);
mantissaAdd(0.06, 0.01);
mantissaAdd(100, -10);
mantissaAdd(-137.2342233, -10);
mantissaAdd(-137.2342233, 10);
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 Comments