Thread: Adding a Large number digit by digit

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    17

    Adding a Large number digit by digit

    Hi, I need to write a program where the user inputs 2 numbers and the program will add these two numbers together digit by digit because it has to be able to handle huge numbers. I am storing the input as strings and converting each digit to an integer when adding them.


    My problem is that the program is giving me weird results (not even numbers) as the sum of the numbers.

    I know my loops are the problem but I'm not sure how to fix them. Please help. Thank you

    Here is my code:
    Code:
    #include "stdafx.h"
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    int main(int argc, char* argv[])
    {
    unsigned char number1 [256];
    unsigned char number2 [256];
    unsigned char result [256];
    int i, y=0, x=0, sum=0, carry=0;
    
    printf ("Please enter a number upto 255 digits long:\n");
    scanf ("%s", number1);
    printf ("Your first number is %s.\n",number1);
    
    printf ("Please enter another number upto 255 digits long:\n");
    scanf ("%s", number2);
    printf ("Your second number is %s.",number2);
    
    
    	for(i=0; i<=256; i++) {
    			number1 [i];
    	}
    	for(y=0; y<=256; y++) {
    			number2 [y];
    	}
    	
    
    
    memset (result, 0, sizeof(result));
    
    for(i=255; i>=0; i--) {
    	sum += carry;
    	for(y=255; y>=0; y--) {
    		sum += number1[i]+number2[y]-48;
    	}
    	carry = sum/10;
    	result[x] = sum%10;
    	x++;
    	sum = 0;
    }
      printf("The sum is %s.", result);
      return 0;
    }

  2. #2
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Code:
    int main(int argc, char* argv[])
    {
    unsigned char number1 [256] = {0};
    unsigned char number2 [256] = {0};
    unsigned char result [256] = {0};
    int i, y=0, x=0, sum=0, carry=0;
    
    ...
    
    memset (result, 0, sizeof(result));
    
    for(i=255; i>=0; i--) {
    	sum += carry;
    	for(y=255; y>=0; y--) {
    		sum += number1[i]+number2[y]-48;
    	}
    ...
    }
    You don't need to use memset to initialise an array, use curly brackets (braces) to it when you declare the variable.
    Also, you're not converting the digits to numbers before you add them and more importantly, why are you subtracting 48??
    Code:
    sum += atoi(number1[i]) + atoi(number2[y]);
    Also, why do you have two loops? Sure you only need one. If I'm not mistaken, your code will add all the digits in number2 to *every* digit in number1

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  3. #3
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Code:
    for(i=0; i<=256; i++)
    the array goes from 0-255, not 0-256.

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Code:
    	for(i=0; i<=256; i++) {
    			number1 [i];
    	}
    	for(y=0; y<=256; y++) {
    			number2 [y];
    	}
    What's that supposed to do? I'd guess that the compiler would optimise that code out of existence, which is fortunate since it might otherwise crash due to buffer overrun.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by mejv3 View Post
    sum += number1[i]+number2[y]-48;
    What is 48? Better to use '0' instead for portability. And it's still not right. EACH of the two numbers has an additional 48 in it, so you actually should be subtracting 96, not 48. Anyway, I would write it like this:

    Code:
    sum += number1[i] - '0' + number2[y] - '0';
    It looks redundant but it makes it clear what is happening.

    There may be other problems. That's as far as I've looked.

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    17
    Here is my code now:

    Code:
    int main(int argc, char* argv[])
    {
    unsigned char number1 [256] = {0};
    unsigned char number2 [256] = {0};
    unsigned char result [256] = {0};
    int i, y=0, x=0, sum=0, carry=0;
    
    printf ("Please enter a number upto 255 digits long:\n");
    scanf ("%s", number1);
    printf ("Your first number is %s.\n",number1);
    
    printf ("Please enter another number upto 255 digits long:\n");
    scanf ("%s", number2);
    printf ("Your second number is %s.",number2);
    
    
    	
    
    
    memset (result, 0, sizeof(result));
    
    
    	for(y=255; y>=0; y--) {
    		sum += carry;
    		sum += number1[y]-'0'+number2[y]-'0';
    		carry = sum/10;
    		result[x] = sum%10;
    		x++;
    		sum = 0;
    }
      printf("The sum is %s.", result);
    
    
      return 0;
    }

    I 've been debugging the code step by step and
    These are my problems now:

    1. I Don't know how to align the numbers if they're different lengths

    ex. 34536216 and 234



    2. If their is an open spot in the array with a 0, 96 is still subtracted from it, which really messes up the sum. Is there a way to convert the number from hex to base 10?

    3. For
    Code:
     result[x] = sum%10;
    , the remainder is getting stored as a weird symbol, not even a number

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    the remainder is getting stored as a weird symbol, not even a number
    result is stored as number 0,1,2 ...
    and you are trying to print the array of numbers as string...
    to do it you should store result as characters '0', '1', ... and null-terminate it

    to convert digit sum&#37;10 into char you should add the '0'
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Registered User
    Join Date
    Oct 2005
    Posts
    17
    Thank you for your help so far, my program has come a long way. It is currently working except when the last number has a carry or the number isn't the same length of digits.
    I know I"m going to have to use a shift some how, but I'm not sure how.

    Here is my as of now:

    Code:
    // CompE271HW2.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    int main(int argc, char* argv[])
    {
    unsigned char number1 [256] = {'0'};
    unsigned char number2 [256] = {'0'};
    unsigned char result [256] = {'0'};
    int i, y=0, sum=0, carry=0;
    
    printf ("Please enter a number upto 255 digits long:\n");
    scanf ("%s", number1);
    printf ("Your first number is %s.\n",number1);
    
    printf ("Please enter another number upto 255 digits long:\n");
    scanf ("%s", number2);
    printf ("Your second number is %s.",number2);
    
    
    memset (result, 0, sizeof(result));
    
    
    	for(y=255; y>=0; y--) {
    		
    BACK:		
    		if( number1[y] == 0) {
    			y--;
    			goto BACK;
    		}
    		else if( number2[y] == 0) {
    			y--;
    			goto BACK;
    		}
    		else{
    		sum += carry;
    		sum += number1[y]-'0'+number2[y]-'0';
    		carry = sum/10;
    		result[y] = sum%10+'0';
    		sum = 0;}
    }
      printf("\nThe sum is %s.", result);
    
    
      return 0;
    }

  9. #9
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    You don't need the single quotes in the initialiser, just zero will suffice. Similarly you don't need memset, the result variable is already initialised to zero.

    And, BY GOD, take out those goto statements! You want the 'continue' keyword to terminate the current loop iteration and start the loop at the next one. In which case you can also take out the y-- int the two if statements.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > And, BY GOD, take out those goto statements!
    Quite so.
    Even the continue is unnecessary since only one branch of the if/else if chain is ever executed, you may as well just let the program flow the normal way.

    In addition, the goto introduces a BUG in that it avoids the loop comparison step to terminate the loop normally. Each y-- should be followed by a y>=0 test, and the goto avoids this.

    > memset (result, 0, sizeof(result));
    So why didn't you use 0 rather than '0' in the initialisation of result to begin with?

    > CompE271HW2.cpp
    You're compiling C code with a C++ compiler. This will lead you astray at some point.
    You can easily do without that stdafx header file as well. Just go to project settings and turn OFF the precompiled headers, you don't need them.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    [QUOTE=Salem;671051Even the continue is unnecessary since only one branch of the if/else if chain is ever executed, you may as well just let the program flow the normal way.
    [/QUOTE]

    In my blind panic at seeing a goto statement in C code, I completely overlooked that
    This is probably what you want:
    Code:
    for (y = 255; y >= 0; --y) {
        if ((number1[y] == 0) || (number2[y] == 0)) {
            continue;
        }
        sum += carry;
        sum += number1[y] - '0' + number2[y] - '0';
        carry = sum / 10;
        result[y] = sum % 10 + '0';
        sum = 0;
    }
    Since you want to terminate the loop iteration if either digit is 0, you may as well use an OR statement. I've also introduced some whitespacing, which makes it nicer to look at. Also when incrementing/decrementing variables with ++/-- and not assigning them to anything, use the prefix operators, as it's cheaper and has the same effect.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Or just invert the test for even more simplicity, and perhaps a bit more obvious as to what it's about
    Code:
    if ( (number1[y] != 0) && (number2[y] != 0) ) {
        sum += carry;
        sum += number1[y] - '0' + number2[y] - '0';
        carry = sum / 10;
        result[y] = sum % 10 + '0';
        sum = 0;
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by QuantumPete View Post
    Also when incrementing/decrementing variables with ++/-- and not assigning them to anything, use the prefix operators, as it's cheaper and has the same effect.
    Sorry for side-tracking and being pedantic, but: is there any evidence of that?

    If there's no assignment or other use of the variable in the same statement, I can't see how it would make any difference. In x86 the code should still be "inc <something>" or "dec <something>" [unless it's a pointer, in which case the inc/dec is replaced by add/sub with a constant of sizeof(*pointer)].

    In some cases, using the right way around of *p++ or *--p would perhaps cause better code on for example PDP-11, VAX or 68K, as those processors have "mov rA,(rB)+" and "mov rA,-(rB)", where the register rB is incremented/decremened automatically "at the same time as the access to memory" - but that would be specific to certain architectures, and definitely doesn't apply to the above case you described.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    As to the "unequal length", just pad the number with zeros (at the beginning) until the shorter one is equal in length with the longer one. This process is called "normalization".

    I'd also set sum = 0 at the beginning of the for-loop, rather than at the end [inside the if-statement as per Salem's suggestion] - it just makes it clearer. You can then (if you want) remove the sum = 0 in the beginning of the code - or even move int sum = 0 inside the braces that enclose the code to add things.

    If you know the length of the string [which you will do after you've normalize the numbers] you can use the length as a start position rather than 255.

    If you add a further zero at the beginning of each of the strings, you don't have to worry about the carry on the last add. Just remove the zero (if you want to) when you're finished, assuming it's still zero (no carry over). Alternatively, check carry after the calculation loop and insert it ahead of the rest of the digits.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    If there's no assignment or other use of the variable in the same statement, I can't see how it would make any difference.
    I agree. The difference would come in C++, where an overloaded postfix operator++ implementation would typically involve a temporary but an overloaded prefix operator++ implementation would operate on *this directly. For primitive types, and thus for C in general, there should be no difference.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. help with prime factor for 12 digit number
    By nick2 in forum C Programming
    Replies: 15
    Last Post: 06-19-2009, 04:39 AM
  2. Number Guessing
    By blacknapalm in forum C Programming
    Replies: 2
    Last Post: 10-01-2008, 01:48 AM
  3. Nim Trainer
    By guesst in forum Game Programming
    Replies: 3
    Last Post: 05-04-2008, 04:11 PM
  4. Need help getting program print out the digit in words
    By cosmiccomputing in forum C Programming
    Replies: 26
    Last Post: 04-24-2008, 08:28 AM
  5. Array of boolean
    By DMaxJ in forum C++ Programming
    Replies: 11
    Last Post: 10-25-2001, 11:45 PM