loading...

Daily Challenge #119 - Adding Big Numbers

thepracticaldev profile image dev.to staff ・1 min read

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

pic
Editor guide
Collapse
ynndvn profile image
La blatte

A simple oneliner in JS:

f=(a,b)=>""+(+a+(+b))
Collapse
idanarye profile image
Collapse
kiliman profile image
Kiliman

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
jbristow profile image
Jon Bristow

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
ujaehrig

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
wheatup profile image
Hao

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

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

A more cool JS solution:

add = (x, y) => (BigInt(x) + BigInt(y)).toString(10)
Collapse
natonathan profile image
Nathan Tamez

python

def add(a, b):
    return (f'{int(a)+int(b)}')
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

JS

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

||

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