DEV Community

Daily Challenge #119 - Adding Big Numbers

dev.to staff on November 18, 2019

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 f...
Collapse
 
kiliman profile image
Kiliman • Edited

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

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
 
ynndvn profile image
La blatte

A simple oneliner in JS:

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

Can't you just do that with jQuery?

Collapse
 
jbristow profile image
Jon Bristow • Edited

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
 
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
 
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
 
erezwanderman profile image
erezwanderman

A more cool JS solution:

add = (x, y) => (BigInt(x) + BigInt(y)).toString(10)
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

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

python

def add(a, b):
    return (f'{int(a)+int(b)}')