'Javascript: How can I add two strings without converting into numbers?

Given two numbers in string format (eg. '10.23' and '25.69') how can I get their sum without converting the string into numbers? (eg '35.92') I do not want to convert the strings into numbers using things like parseInt, Number, parseFloat etc....



Solution 1:[1]

An old trick is to multiply by 1, as that forces numeric conversion. The * operator doesn't work on strings, so it forces a switch to numbers. It's an old trick though, as I said.

The unary plus operator is a more modern.

var num1 = '20',
    num2 = '30.5';

console.log(num1 * 1 + num2 * 1); // = '50.5'

If you want the output to definitely be a string, you can also:

console.log((num1 * 1 + num2 * 1)+"");

Solution 2:[2]

Disclaimer: I am not recommending you actually do this. However, you could implement your own add method using a pre calculated lookup table and a rough implementation of a "binary" adder (converted into decimal). The code below work for your example, but i leave no guarantee that it will work for any general cases.

const lookupTable = Array(10).fill(0)
  .map((_, i) => Array(10).fill(0)
    .map((_, j) => [`${i},${j}`, i+j+'']))
  .reduce((flatArr, innerArr) => [...flatArr, ...innerArr], [])
  .reduce((lookupTable, [k, v]) => ({...lookupTable, [k]: v}), {})

const addDigits = (a, b) => {
  const sum = lookupTable[`${a},${b}`];
  if (sum.length === 2) return [sum[1], '1'];
  else return [sum, '0'];
}

const strAdd = (a, b) => {
  const add = ([aH, ...aT], [bH, ...bT], carryBit='0') => {
    if (aH === undefined && aH === undefined) return '';
    if (aH === undefined) return add([], bT, carryBit) + bH;
    if (bH === undefined) return add(aT, [], carryBit) + aH;
    if (aH === '.' || bH === '.') return add(aT, bT, carryBit) + '.';
    const [partial_sum, partial_carryBit1] = addDigits(aH, bH);
    const [sum, partial_carryBit2] = addDigits(partial_sum, carryBit);
    const [newCarryBit] = addDigits(partial_carryBit1, partial_carryBit2);
    return add(aT, bT, newCarryBit) + sum;
  }
  const [whole_a, decimal_a] = a.split('.');
  const [whole_b, decimal_b] = b.split('.');
  const wholeMaxLength = Math.max(whole_a.length, whole_b.length)+1;
  const decimalMaxLength = Math.max((decimal_a || '0').length, (decimal_b || '0').length);
  a = whole_a.padStart(wholeMaxLength, '0') + '.' + (decimal_a || '').padEnd(decimalMaxLength, '0');
  b = whole_b.padStart(wholeMaxLength, '0') + '.' + (decimal_b || '').padEnd(decimalMaxLength, '0');
  return add([...a].reverse(), [...b].reverse(), '0')
    .replace(/^0+/, '') // remove leading 0
    .replace(/0+$/, '') // remove trailing 0
    .replace(/\.$/, '') // remove trailing .
}

const calc = (a, b, expected) => {
  const result = strAdd(a, b);
  console.log(result, result === expected);
}

calc('10.23', '25.69', '35.92');
calc('1', '2', '3');
calc('10.3', '2', '12.3');
calc('99999', '1.01', '100000.01');

Solution 3:[3]

Here's the solution for your problem:

const format_numStr = (num, no_of_digits, digits_Arr) => {
    
    outNum = 0

    no_of_digits-=1
    
    for (digit of num) {
        
        if (digits_Arr.includes(digit)) {

            // power of 10 decreases as digits progress from left to right i.e from 10^(len(num)-1) to 10^0 
            
            // index() Method returns the exact number or digit we pass in type integer

            outNum+=(digits_Arr.indexOf(digit)*10**(no_of_digits))

            no_of_digits-=1
        }
    };

    return outNum
}


const numStr_Sum = (numStr_Arr) => {

    digits_Arr = Array.from(new Array(10), (_, i) => String(i)) //array contains digits from [0-9]

    num_Arr=[]  // Initialise an array to store the given str number as type integer

    numStr_Arr.forEach(num => {

        no_of_digits = num.length

        if (num.includes('.')) {

            decimal_val = num.split('.')[1].length      // Gives the Decimal point (.) position value
            
            //Since period(.) exists in the num, no_of_digits should be decreased by 1 
            float_num = format_numStr(num, no_of_digits-1,digits_Arr)/10**decimal_val

            num_Arr.push(float_num)
        
        }
        else {
            num_Arr.push(format_numStr(num, no_of_digits, digits_Arr))
        }
    
    });

    total_sum = num_Arr.reduce((a,b)=>a+b,0)

    if (Number.isInteger(total_sum)) {
        return total_sum
        
    }
    else {
        return total_sum.toFixed(decimal_val)
    }

}


console.log(numStr_Sum(['22.22','22.22']))

Solution 4:[4]

You can use the unary plus operator (+), but in the background it is converting the string into numbers anyway.

Example: +string1 + +string2

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 Gabriel Tetzlaf