DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #119 - Adding Big Numbers

We need to sum big numbers and we require your help.

Write a function that returns the sum of two numbers. The input numbers are strings and the function must return a string.

Example:

add("123", "321"); -> "444"
add("11", "99"); -> "110"

Notes:

  • The input numbers are big.
  • The input is a string of only digits
  • The numbers are positives

This challenge comes from Becojo on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Discussion (18)

Collapse
ynndvn profile image
La blatte

A simple oneliner in JS:

f=(a,b)=>""+(+a+(+b))
Collapse
idanarye profile image
Idan Arye

Can't you just do that with jQuery?

Collapse
kiliman profile image
Kiliman • Edited on

Typescript includes tests

github.com/kiliman/dev-to-daily-ch...

export const add = (a: string, b: string): string => {
  const re = /^\d+$/
  if (!re.test(a) || !re.test(b)) {
    throw new Error(`{a} and {b} must be positive integers`)
  }

  const result = []
  a = a
    .split('')
    .reverse()
    .join('')
  b = b
    .split('')
    .reverse()
    .join('')
  let carry = 0
  for (let i = 0; i < Math.max(a.length, b.length); i++) {
    const a_ = a.length > i ? parseInt(a[i]) : 0
    const b_ = b.length > i ? parseInt(b[i]) : 0
    let sum = a_ + b_ + carry
    carry = Math.floor(sum / 10)
    if (carry !== 0) {
      sum = sum % 10
    }
    result.push(String(sum))
  }
  if (carry > 0) {
    result.push(carry)
  }
  return result.reverse().join('')
}

Test

import { add } from '.'

it('should throw an error if numbers are not all digits', () => {
  expect(() => add('', '')).toThrow()
  expect(() => add('abc', '321')).toThrow()
  expect(() => add('11', 'xyz')).toThrow()
})

it('should return sum of two numbers', () => {
  expect(add('0', '0')).toBe('0')
  expect(add('123', '321')).toBe('444')
  expect(add('11', '99')).toBe('110')
  expect(add('1', '199')).toBe('200')
})

it('should return sum of two really big numbers', () => {
  expect(add('123456789', '987654321')).toBe('1111111110')
  expect(add('12345678910123456789', '987654323109876543210')).toBe(
    '1000000002019999999999',
  )
})
Collapse
wheatup profile image
Hao • Edited on

There's a BigInt type in vanilla javascript, why not just use that instead?

const add = (a, b) => (BigInt(a) + BigInt(b)).toString();
add("10000000000000000000", "3");   // 10000000000000000003
Enter fullscreen mode Exit fullscreen mode
Collapse
svmarinez profile image
Sara Vasquez

BigInt isn't supported for this one. There was another kata that was multiplying big numbers by a different author and they allowed it, but I guess that's not the route they wanted folks to take.

Collapse
jbristow profile image
Jon Bristow • Edited on

Python for arbitrarily large numbers represented as strings:

def large_sum(a: str, b: str) -> str:

    if len(b) < len(a):
        return large_sum(b, a)

    alist = [int(c) for c in reversed(a)]
    blist = [int(c) for c in reversed(b)]

    for _ in range(0, len(alist) - len(blist)):
        blist.append(0)

    overflow = 0
    output = []
    for ax, bx in zip(alist, blist):
        sumval = ax + bx + overflow
        overflow = int((sumval) / 10)
        output.append(sumval % 10)

    if overflow != 0:
        output.append(overflow)

    return "".join(str(i) for i in reversed(output))


print(large_sum("1234", "3456"))
print(
    large_sum(
        "1234567890123456789012345678901234567890",
        "456789012345678901234567890123456789012345678901234567890123",
    )
)
print(large_sum("44", "2"))

Collapse
ujaehrig profile image
Ulf Jährig

Java


import java.math.BigDecimal;

class Adder {
    public static String add(String arg1, String arg2) {
        return new BigDecimal(arg1).add(new BigDecimal(arg2)).toString();
    }
}

Collapse
kesprit profile image
kesprit

Swift function :

func sum(first: String, second: String) -> String {
    return "\((Int(first) ?? 0) + (Int(second) ?? 0))"
}

And with a closure :

let _ = { (first: String, second: String) -> String in
    "\((Int(first) ?? 0) + (Int(second) ?? 0))"
}
Collapse
idanarye profile image
Idan Arye

Isn't Int a sized integer? It won't work with numbers that don't fit in 64 bits (or 32 bits, if you compile it for 32 bit architectures)

Collapse
erezwanderman profile image
erezwanderman

Javascript

add = (x, y) => {
    const l = Math.max(x.length, y.length);
    const r = Array(l).fill().reduce(
        (a, _, i) => [
            (a[1] + +(x[x.length - 1 - i] || '0') + +(y[y.length - 1 - i] || '0')) % 10 + a[0],
            +((a[1] + +(x[x.length - 1 - i] || '0') + +(y[y.length - 1 - i] || '0')) > 9)
        ],
        ['', 0]);
    return '' + (r[1] ? r[1] : '') + r[0]
}
Collapse
idanarye profile image
Idan Arye

Rust:

fn add(num1: &str, num2: &str) -> Result<String, String> {
    const ZERO_CHAR: u8 = '0' as u8;
    let mut reversed_result = Vec::<u8>::new();
    let max_digits = num1.len().max(num2.len());

    macro_rules! convert_num {
        ($num:expr) => {
            $num.chars().rev().chain(['0'].iter().cloned().cycle())
        }
    }

    let digits1 = convert_num!(num1);
    let digits2 = convert_num!(num2);

    let mut carry = 0;
    for (digit1, digit2) in digits1.zip(digits2).take(max_digits) {
        fn digit_to_numeric(digit: char) -> Result<u8, String> {
            if '0' <= digit && digit <= '9' {
                Ok(digit as u8 - ZERO_CHAR)
            } else {
                Err(format!("{:?} is not a digit", digit))
            }
        }

        let digit1 = digit_to_numeric(digit1)?;
        let digit2 = digit_to_numeric(digit2)?;

        let digit_sum = digit1 + digit2 + carry;
        carry = digit_sum / 10;
        assert!(carry < 10);
        reversed_result.push(digit_sum % 10 + ZERO_CHAR);
    }
    if 0 < carry {
        reversed_result.push(carry + ZERO_CHAR);
    }
    reversed_result.reverse();
    Ok(String::from_utf8(reversed_result).expect("We only added digits"))
}
Collapse
peter279k profile image
peter279k

Here is the simple solution with JavaScript:

function add(a, b) {
  var ans = "";

  if (a.length > b.length ) {
    var zeroLength = a.length - b.length;

    for (var index=0; index<zeroLength; index++) {
      b = "0" + b;
    }
  }

  if (a.length < b.length ) {
    var zeroLength = b.length - a.length;

    for (var index=0; index<zeroLength; index++) {
      a = "0" + a;
    }
  }

  var step = [];
  if (a.length === b.length) {
    for (var index=a.length-1; index>=0; index--) {
      var numberA = Number(a[index]);
      var numberB = Number(b[index]);
      var addResult = 0;
      if (step[index+1]) {
        addResult = step[index+1] + numberA + numberB;
      } else {
        addResult = numberA + numberB;
      }
      if (addResult >= 10 && index !== 0) {
        ans = String(addResult - 10) + ans;
        step[index] = 1;
      } else {
        ans = String(addResult) + ans;
      }
    }
  }

  return ans;
}
Collapse
yechielk profile image
Yechiel Kalmenson

Ruby:

def add(a, b)
    (a.to_i + b.to_i).to_s
end
Collapse
fitsum profile image
fitsum • Edited on

JS

add = (one, tew)=>{return (Number(one) + Number(tew)).toString()}

||

add2 = (...input) =>{ return input.reduce((acc,curr)=>{return (acc + Number(curr)).toString()})}

Collapse
natonathan profile image
Nathan Tamez • Edited on

python

def add(a, b):
    return (f'{int(a)+int(b)}')
Collapse
erezwanderman profile image
erezwanderman

A more cool JS solution:

add = (x, y) => (BigInt(x) + BigInt(y)).toString(10)