help with ugly code

This function treats two strings like they are ints and adds them. But the code looks long and has too many temporary variables for my liking. It is also confusing to try and follow. Can any one come up with a better way of doing this? Oh, and the checkstring function call just makes sure there are no letters or symbols in the string, just numbers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
string add(const string &a, const string &b) {
	int temp;
	if (!checkstring(a) || !checkstring(b)) {
		return "Not a number.";
	}
	string top, bottom, result;
	if (a.size() >= b.size()) {
		top = a;
		bottom = b;
	}
	else {
		top = b;
		bottom = a;
	}
	int i = top.size();
	int j = bottom.size();
	int carry = 0;
	for (i, j; i > 0 && j > 0; i--, j--) {
		temp = stoi(top.substr(i - 1, 1)) + stoi(bottom.substr(j - 1,1));
		if (temp >= 10) {
			result.insert(0, to_string(temp % 10 + carry));
			carry = temp / 10;
		}
		else {
			result.insert(0, to_string(temp + carry));
			carry = 0;
		}
		if (i - 1 == 0 && carry > 0) {
			result.insert(0, to_string(carry));
		}
	}
	for (i; i > 0; i--) {
		temp = stoi(top.substr(i - 1, 1));
		if (temp + carry >= 10) {
			result.insert(0, to_string((temp + carry) % 10));
			carry = (temp + carry) / 10;
		}
		else {
			result.insert(0, to_string(temp + carry));
			carry = 0;
		}
		if (i - 1 == 0 && carry > 0) {
			result.insert(0, to_string(carry));
		}
	}
	return result;
}
1
2
3
4
string add(const string &a, const string &b)
{
  return to_string(stoi(a) + stoi(b));
}


Add exception catching or error checking for invalid strings as you like. If you feed it strings representing really big numbers it won't work, though. Do you need that too?
Last edited on
Well, yes... the point of this exercise was to be able to add numbers that are too big for ints, numbers of near infinite length. The kind of numbers that codechef makes you deal with...

It is going to be part of a new class I am working on called infInt (short for infinity int.)
Last edited on
Here's a class that only adds nonnegative integers using naive long addition.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
struct primitive_bignum
{
  explicit primitive_bignum(std::string_view n = "0")
    : strvalue(n.rbegin(), n.rend())
  {
    if (!digits_only(strvalue))
      throw std::invalid_argument("contains nondigits");
  }

  primitive_bignum &operator+=(primitive_bignum const &rhs)
  {
    std::string new_value;

    auto const n_digits = std::max(strvalue.size(), rhs.strvalue.size());

    int carry = 0;
    for (size_type i = 0; i < n_digits; ++i) {
      auto const sum = digit(i) + rhs.digit(i) + carry, new_digit = sum % 10;
      carry = sum / 10;

      new_value.push_back(new_digit + '0');
    }

    if (carry)
      new_value.push_back('1');

    strvalue = std::move(new_value);
    return *this;
  }

  std::string str() const
  {
    return { strvalue.rbegin(), strvalue.rend() };
  }

  using size_type = std::string::size_type;

private:
  static bool digits_only(std::string_view s) noexcept
  {
    return s.find_first_not_of("0123456789") == std::string_view::npos;
  }

  int digit(size_type n) const noexcept
  {
    return (n < strvalue.size()) ? strvalue[ n ] - '0' : 0;
  }

  std::string strvalue;
}


Live demo:
http://coliru.stacked-crooked.com/a/d4ebde7da56cdd2b

Last edited on
Thanks mbozzi, but I did mine in 47 lines of code to your 56. I guess I was hoping there was some magical short hand that did this.
@Manga,
IMO it's better to focus on writing code that is easily understandable, fast, testable, maintainable, extendible even it is more verbose.
For example the Dependency inversion principle is an important SOLID priciple, but adding additional classes and interfaces will lead to more code.
the point of this exercise was to be able to add numbers that are too big for ints

There was a thread about this a long time ago... http://www.cplusplus.com/forum/lounge/32041/
Might provide some inspiration. In particular, fun2code's idea to use a radix of 10000 is really nice,
as it combines performance (vs radix 10) and easy parsing / printing (vs a 2^n radix).
Last edited on
Thanks toad, that is interesting stuff. Definitely worth further study.
OK so I have a class that has a private member string s.
How can I overload the << operator so that I could code
1
2
infInt bob;
cout << bob;
and the output would be bob's string member bob.s?
Last edited on
In your declaration, something like: friend ostream& operator<<(ostream& os, const infInt& someValue);

and somewhere else:
1
2
3
4
5
ostream& operator<<(ostream& os, const infInt& someValue)  
{  
    os << someValue.s;
    return os;  
}  

Yes! That did it repeater. Thanks!!
Topic archived. No new replies allowed.