0
unsigned long long a = 18446744073709551615
unsigned long long b = 18446744073709551614
unsigned long long c = 18446744073709551613
unsigned long long d = 18446744073709551612
unsigned long long e = 18446744073709551611

I'd like to add a+b+c+d+e and get both the result (64 bits) and the carry because it'll exceed 64 bits. Should I use BigInteger library for this? Are there any easier ways to do such thing? Most of the stuff I found using BigInteger is little bit complicated and I could not find very similar examples although my question seems straightforward.

DeiDei
  • 10,205
  • 6
  • 55
  • 80
Mint.K
  • 849
  • 1
  • 11
  • 27
  • If you want to stay portable and lean you can't get away from using BigInt, either your own or an external library. Otherwise some assembly won't hurt you. x86_64 has a 128bit integer as well. – DeiDei Jun 02 '17 at 07:58
  • You can divide your 64bit values into low 32bit values and high 32bit values, than sum low 32bit values as 64 bit and get sum and overflow, than similary sum high parts and overflow from low parts, and so you'll have lower 32 bit of result, higher 32 bit of result and overflow – Andrew Kashpur Jun 02 '17 at 08:10

1 Answers1

3

If you only need to do addition

#include<cstdint>
#include<limits>
#include<utility>

using std::uint64_t;

std::pair<uint64_t, int> add_with_carry(uint64_t a, uint64_t b)
{
    if(a > std::numeric_limits<uint64_t>::max() - b)
        return {a + b, 1};
    else
        return {a + b, 0};
}

auto [sum, carry] = add_with_carry(a, b);

And to extend to arbitrary chained additions

std::pair<uint64_t, int> add_with_carry(std::pair<uint64_t, int> a)
{
    return a;
}

template<typename... Addends>
std::pair<uint64_t, int> add_with_carry(std::pair<uint64_t, int> a, uint64_t b, Addends... addends)
{
    if(b > std::numeric_limits<uint64_t>::max() - a.first)
        return add_with_carry(std::pair<uint64_t, int>{b + a.first, 1 + a.second}, addends...);
    else
        return add_with_carry(std::pair<uint64_t, int>{b + a.first, a.second}, addends...);
}

template<typename... Addends>
std::pair<uint64_t, int> add_with_carry(uint64_t a, Addends... addends)
{
    return add_with_carry(std::pair<uint64_t, int>{a, 0}, addends...);
}

auto [sum, carry] = add_with_carry(a, b, c, d, e);

There might be a more elegant way to implement this with fold expressions.

Caveat: You might overflow the carry int if you have 2 billion variables in a call to add_with_carry. Good luck with that though...

Passer By
  • 19,325
  • 6
  • 49
  • 96
  • 1
    do you think you can demonstrate (using your function in main())how I can get the result and carry by using your chained additions version, please? – Mint.K Jun 02 '17 at 08:20
  • @Mint.K I was actually only half done then :P. Here's the example – Passer By Jun 02 '17 at 08:34