CS 2213 Advanced Programming
Multiple Precision Arithmetic



Overview

When integers are stored in a computer, the precision is usually limited by the hardware of the machine or restrictions on the programming language used.

We will look at a simple method of doing arithmetic (add, subtract, multiply) for integers which may be very large.
We will use a representation which is particularly simple to make our algorithms easy to implement.


Integer Format

We will assume a constant INTSIZE has been defined and we will store integers in arrays of characters of this size. Suppose we have:
char a[INTSIZE];


Checking for valid values

While debugging code that assumes data structures will be in a particular format, it is useful to be able to check that the format is valid.

/* Return as follows:
     0:        OK
     -1:       bad sign
     INTSIZE:  no digits, just blanks
     n         position of first invalid digit
*/
int checkvalid(char a[]) {
   int i;

   if ( (a[0] != '+') && (a[0] != '-') ) return -1;

   for (i=1;i<INTSIZE;i++)
     if (a[i] != ' ') break;
   if (i == INTSIZE) return INTSIZE;
   if ( (i == INTSIZE-1) && (a[i]=='0') && (a[0]=='-') ) return -1;
   if ( (i < INTSIZE-1) && (a[i]=='0') ) return i;


   for ( ; i<INTSIZE;i++)
     if ( (a[i] < '0') || (a[i] > '9') ) return i;

   return 0;
}


Functions to write

The file arithmetic.h will contain the definitions and function prototypes we will need:
#define INTSIZE 50

int checkvalid(char a[]);
int readint(char a[]);
void printint(char a[]);
int addint(char a[], char b[], char c[]);
int subint(char a[], char b[], char c[]);
int multint(char a[], char b[], char c[]);
We have already looked at checkvalid.

readint will read in a line from standard input and store the result in the array a in the appropriate format. It will return 0 if successful and 1 if an error occurs. The leading sign will be optional and it will ignore leading blanks on the input.

What are the possible error conditions?







Here is a version you can use:
int readint(char a[]) {
   int count;
   int i;
   int j;
   int c;

   count = 0;
   while ((c = getchar()) == ' ');       /* skip leading blanks */
   if ( (c == '\n') || (c == EOF) )
      return 1;                          /* premature end of file */
   if (c == '-') a[0] = '-';             /* put in sign */
   else {
      a[0] = '+';
      if (c != '+')                      /* or first digit */
          a[++count] = (char)c;
   }
   while ( ((c=getchar()) !='\n') && (c!=EOF) ) { /* go until EOL or EOF */
      if (count >= INTSIZE-1)                     /* not enough room */
         return 1;
      a[++count] = (char)c;                       /* put it in, adjust count */
   }
   if (count == 0) return 1;                      /* nothing was put in */
   for (i=1;i<=count;i++)                        /* check that all are digits */
      if ( (a[i] < '0') || (a[i] > '9') )
         return 1;
   for (i=count,j=INTSIZE-1;i>0;i--,j--)      /* move them to the right place */
      a[j] = a[i];
   while (j > 0)                              /* fill beginning with blanks */
      a[j--] = ' ';
   return 0;
}

printint prints out the integer to standard output with the leading sign but not the leading blanks. It assumes that the array is valid.

addint puts the result of a + b in c if the result will fit and returns 0 in this case. It returns 1 if there is an overflow. It assumes that a and b are valid and that c is an array of the appropriate size.

subint and multint are similar.


Some useful functions

These will be in arithmetic.c but will be declared static so they can not be accessed from outside.

int addposint(char a[], char b[], char c[]);
will add a and b and put the result in c ignoring the signs of a and b assuming they are positive. The return value will be like addint.

void subposint(char a[], char b[], char c[]);
will be similar but will subtract b from a assuming that a is at least as big as b. This will never produce an error.

int greater(char a[], char b[]);
will return true if a is at least as big as b ignoring the signs of a and b.

From these it will be simple to write addint and subint by looking at the various cases.

Here are some issues to keep in mind when writing addposint

Let us try to write int addint(char a[], char b[], char c[]) given these functions.

This is what we got done in class on Tuesday, January 23:

int addint(char a[], char b[], char c[]) {
   if ( (a[0]=='+') && (b[0]=='+') )
      return addposint(a,b,c);
   if ( (a[0]=='-') && (b[0]=='-') ) {
      if (addposint(a,b,c) != 0) return 1;
      c[0] = '-';
      return 0;
   }
   if (greater(a,b)) {
   ...
   }
}