The goal of this library is to produce all the utility routines necessary to work with arbitrarily large numbers.
//
// LargeNumber library
//
// authors: Isaac Traxler & students
//
// This is a project started back in 2000 that was not finished
// and forgotten. It has now been resurrected.
//
// The goal of this project is to produce a usable c source library
// for large number arithmetic.
//
// Students in my Psychology of Programming class in 2000 contributed.
// Since I have largely restructured it, individual names have been
// removed from the individual routines. So here are the names of the
// original contributing students:
// - Paul Miller
// - Wojciech Stryjewski
// - Phil Bordelon
// - John Walker
// - Erin Valentine
// - Jay Ponville
// - Jamie Ahmad
// - Helen
//
// Contributed to revamped version:
// - Josh Abadie
//
#include <ctype.h>
//
// Make sure that LN_MAX_DIGITS is large enough to handle worst case.
// Be aware that as many as 5 LN instances might exist in a routine.
// Be aware that excessively large values will result in CPU consumption
// in certain situations (like division of repeating decimals).
//
#define LN_MAX_DIGITS 1000
typedef struct LARGE_NUMBER_STRUCT
{
unsigned short int array[LN_MAX_DIGITS]; // might consider unsigned char here
// to reduce storage by 50%
signed short int sign;
signed long int exponent;
signed short int digitCount;
}
LARGE_NUMBER_STRUCT;
//
// ASSUMPTIONS:
// 1) That no value sent to the library will exceed bounds
// a) Exponent will fit into a signed long at ALL times
// b) Significant digit count will not exceed LN_MAX_DIGITS
//
// 2) LN instances are ALWAYS normalized when passed into a routine
//
// 3) Adding or subtracting two 501 digit numbers can exceed 1000 digits
//
// 4) No bounds checking is done against LN_MAX_DIGITS
//
// 5) Normalization does the following:
// a) Adjusts exponent, adjusts digitCount, and removes leading zeroes
// b) Adjusts digitCount and removes trailing zeroes
// c) Leaves number so that a decimal point is implied before the first digit
//
//
// ********************************************************************************
// rules:
// - all routines return 0 if everything is okay, a different positive number
// for each different error
// - Any result passed back (except from LNshift) is normalized
// - LNadd adds any two numbers with same sign (calls subtract if signs differ)
// - LNsubtract subtracts any two numbers with same sign (calls add if signs differ)
//
// a = 1
// b = -1
// add(a,b,c) ==> subtract(a,(-b),c)
// subtract(a,b,c) ==> add(a,(-b),c)
//
// - 0 ALWAYS has a + sign and an exponent of 0
//
//
void LNprint(LARGE_NUMBER_STRUCT *n)
// simple routine to print large number
{ // BEGIN function LNprint -- (200302)
char str[LN_MAX_DIGITS+25];
LNarr2strExp(n, str);
printf("[%s]\n", str);
} // END function LNprint -- (200302)
int LNnegate(LARGE_NUMBER_STRUCT *ln1)
// changes sign of ln1
{ // BEGIN function LNnegate -- (200302)
if (0 != ln1->digitCount)
ln1->sign *= -1;
return 0;
} // END function LNnegate -- (200302)
int LNcompare(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2)
// compares to see if a<b (-1), a=b (0), a>b (1); assumes both numbers
// are normalized (have first digit non-zero and no trailing zeros)
{ // BEGIN function LNcompare -- (200303)
int toReturn = 0;
// XOR the two, if same 0 (false) results, if different -2 (true)
if (ln1->sign ^ ln2->sign) // signs are same, result is 0
{ // have different signs
toReturn = (0 > ln1->sign) ? -1 : 1;
} // have different signs
else
{ // have same sign
if (ln1->exponent != ln2->exponent)
{ // exponents not equal, return 1 (1st one) or -1 (2nd one) to show larger
toReturn = (ln1->exponent > ln2->exponent) ? 1 : -1;
} // exponents not equal, return 1 (1st one) or -1 (2nd one) to show larger
else
{ // numbers have same exponent
int i, t;
t = (ln1->digitCount > ln2->digitCount) ? ln2->digitCount : ln1->digitCount;
for (i=0; (i<t) && (0 == toReturn) ; i++)
{ // for - compare each digit
if (ln1->array[i] != ln2->array[i])
toReturn = (ln1->array[i] > ln2->array[i]) ? ln1->sign : - ln2->sign;
} // for - compare each digit
// digits identical, but one number has extra digits, so number with extra digits
// is bigger if positive, smaller if negative.
if ((0 == toReturn) && (ln1->digitCount != ln2->digitCount))
toReturn = (ln1->digitCount > ln2->digitCount) ? ln1->sign : - ln2->sign;
} // numbers have same exponent
} // have same sign
return toReturn;
} // END function LNcompare -- (200303)
int LNstr2arr(char str[], LARGE_NUMBER_STRUCT *ln)
// convert from string into LN data structure
// assume no invalid characters in string (but skip over leading and trailing blanks)
//
// State diagram:
//
// state | val | whitespace | - | + | . | digit | Ee | end of string`
// ------+-----+------------+------+------+------+-------+------+--------------
// start | 1 | start | num1 | num1 | dec1 | num2 | err | 0
// num1 | 2 | err | err | err | dec1 | num2 | err | err
// num2 | 3 | normalize | err | err | dec2 | num2 | exp1 | normalize
// dec1 | 4 | err | err | err | err | dec2 | err | err
// dec2 | 5 | normalize | err | err | err | dec2 | exp1 | normalize
// exp1 | 6 | err | exp2 | exp2 | err | exp3 | err | err
// exp2 | 7 | err | err | err | err | exp3 | err | err
// exp3 | 8 | normalize | err | err | err | exp3 | err | normalize
{ // BEGIN function LNstr2arr -- (200302)
#define START 1
#define NUM1 2
#define NUM2 3
#define DEC1 4
#define DEC2 5
#define EXP1 6
#define EXP2 7
#define EXP3 8
//
// status - (succes/failure) flag (init to SUCCESS)
// done - are we done yet? (init to NO)
// dpflag - decimal point flag - Have we encountered one yet? (init to NO)
// numflag - number flag - Have we encountered any NON-ZERO digits yet? (init to NO)
// n - counter/subscript for large number (init to start)
// ch - point to main string
// These next two need not be used if their values are stored directly into large number.
// sign
// exp
//
int state = START, done = 0, n = 0;
signed short int dpflag = 0, numflag = 0, sign = 1;
signed long int exp;
char *ch = str;
// skip leading blanks and leading zeroes (start < > start)
while ( (isspace(*ch)) || ('0' == *ch) ) ch++;
if (0 != *ch) // is it end of string?
{ // not empty string
// do we have a sign (must be first char)
if ('-' == *ch)
{ // negative - state is NUM1
sign = -1;
ch++;
} // negative - state is NUM1
else
// Check for plus sign: Not really necessary...(these 4 lines may
// be omitted) if numbers are not going to have unary pluses
if (*ch == '+')
{ // positive (the default) - state is NUM1
ch++;
} // positive (the default) - state is NUM1
// now get digits until the decimal point or exponent
while (isdigit(*ch))
{ // process digits -- into state NUM2
state = NUM2;
ln->array[n++] = *ch - '0';
ch++; // move to next char in string
} // process digits -- into state NUM2
exp = n;
if ('.' == *ch)
{ // decimal point
// set state to DEC1 if no digits, DEC2 if digits already
state = (NUM2 != state) ? DEC1 : DEC2;
ch++;
// now get digits after the decimal point
if (isdigit(*ch)) state = DEC2;
while (isdigit(*ch))
{ // process digits -- into state NUM2
ln->array[n++] = *ch - '0';
ch++; // move to next char in string
} // process digits -- into state NUM2
} // decimal point
// only things left are Ee (exponent), whitespace and end of string
if (('E' == *ch) || ('e' == *ch))
{ // okay we have an exponent
signed long int texp;
state = EXP2;
ch++;
sscanf(ch, "%d", &texp);
exp += texp;
} // okay we have an exponent
} // not empty string
if ((EXP2 == state) || (DEC2 == state) || (NUM2 == state))
{ // normalize number
ln->sign = sign;
ln->exponent = exp;
ln->digitCount = n;
state = 0;
} // normalize number
return state;
} // END function LNstr2arr -- (200302)
int LNicnvrt(long int number, LARGE_NUMBER_STRUCT *n)
// convert a long int to Large Number
{ // BEGIN function LNicnvrt -- (200302)
int idx, digit, j;
// do sign
n->sign = (number < 0) ? -1 : 1;
// set mantissa and exponent
n->exponent = 0;
idx = LN_MAX_DIGITS;
while (number > 0)
{ // while
digit = number % 10;
n->array[--idx] = digit;
number /= 10;
} // while
n->exponent = LN_MAX_DIGITS - idx;
n->digitCount = n->exponent;
for (j=0; LN_MAX_DIGITS > (j + idx); j++)
{ // for
n->array[j] = n->array[idx+j];
} // for
return 0;
} // END function LNicnvrt -- (200302)
int LNarr2strExp(LARGE_NUMBER_STRUCT *ln, char str[])
// convert the ln struct to a string in scientific notation
{ // BEGIN function LNarr2strExp -- (200302)
int i, cnt = 0;
if (0 == ln->digitCount)
{ // handle zero
strncpy("+0E0", str);
} // handle zero
else
{ // handle non-zero
str[cnt++] = (0 > ln->sign) ? '-' : '+';
str[cnt++] = '0' + ln->array[0];
str[cnt++] = '.';
for (i = 1; i < ln->digitCount; i++)
str[cnt++] = '0' + ln->array[i];
str[cnt++] = 'E';
sprintf(&(str[cnt]), "%+ld", (ln->exponent-1));
} // handle non-zero
return 0;
} // END function LNarr2strExp -- (200302)
int LNarr2strInt(LARGE_NUMBER_STRUCT *ln, char str[])
// convert the ln struct to a string n integer format with truncate
{ // BEGIN function LNarr2strInt -- (200302)
int i, cnt = 0;
if ((0 > ln->exponent) || (0 >= ln->digitCount))
{ // abs(number) less than 0 or number is zero
strncpy("+0", str);
} // abs(number) less than 0 or number is zero
else
{ // something to convert
int x;
str[cnt++] = (0 > ln->sign) ? '-' : '+';
x = (ln->exponent > ln->digitCount) ? ln->digitCount : ln->exponent;
for (i = 0; i < x; i++)
str[cnt++] = '0' + ln->array[i];
x = ln->exponent - ln->digitCount;
for (i=0; i < x; i++)
str[cnt++] = '0';
str[cnt] = 0;
} // something to convert
return 0;
} // END function LNstrInt -- (200302)
int LNln2strFloat(LARGE_NUMBER_STRUCT *ln, char str[])
// convert the ln struct to a string in float format
{ // BEGIN function LNln2strFloat -- (200302)
int i, cnt = 0;
if (0 == ln->digitCount)
{ // hadle 0
strncpy("+0.0", str);
} // hadle 0
else
{ // not zero
int x1, x2;
str[cnt++] = (0 > ln->sign) ? '-' : '+';
x1 = (ln->exponent > ln->digitCount) ? ln->digitCount : ln->exponent;
for (i = 0; i < x1; i++)
str[cnt++] = '0' + ln->array[i];
x2 = ln->exponent - ln->digitCount;
if (0 > x2)
{ // digitCount larger
str[cnt++] = '.';
for (i = x1; i < ln->digitCount; i++)
str[cnt++] = '0' + ln->array[i];
} // digitCount larger
else
{ // exponent larger
for (i=0; i < x2; i++)
str[cnt++] = '0';
str[cnt++] = '.';
str[cnt++] = '0';
} // exponent larger
str[cnt++] = 0;
} // not zero
return 0;
} // END function LNstrFloat -- (200302)
int LNshift(LARGE_NUMBER_STRUCT *ln, int cnt)
// shift the implied decimal point
{ // BEGIN function LiNshift -- (200302)
// errorLevel - Errorlevel to return.
// i - Loop variable.
int i, errorLevel = 0;
if (0 < ln->digitCount)
if (0 < cnt)
{ // non-negative - do the shift
for ((i = ln->digitCount - 1); i >= 0 ; i --)
ln->array[i + cnt] = ln->array[i];
for (i = 0; i < cnt; i ++)
ln->array[i] = 0;
ln->exponent += cnt;
ln->digitCount += cnt;
} // non-negative - do the shift
else
if (0 != cnt)
{ // can't do it
fprintf (stderr, "Error: Cannot shift negative bits.\n");
errorLevel = 1;
} // can't do it
return errorLevel;
} // END function LNshift -- (200302)
int LNnormalize(LARGE_NUMBER_STRUCT *ln)
// fix LN so that arr[0] <> 0 (if possible)
{ // BEGIN function LNnormalize -- (200302)
// errorLevel - Errorlevel to return.
// zeroCount - How many zeroes?
// i - Loop variable
int i, errorLevel = 0, zeroCount = 0;
if (0 < ln->digitCount)
{ // digits to process
while ((ln->array[zeroCount] == 0) && (zeroCount < ln->digitCount))
{ // count leading zeroes
zeroCount ++;
} // count leading zeroes
if (0 < zeroCount)
{ // found leading zeroes
if (zeroCount == ln->digitCount)
{ // entire number is zero
ln->exponent = 0;
ln->digitCount = 0;
ln->sign = 1;
} // entire number is zero
else
{ // digits to shift
ln->digitCount -= zeroCount;
ln->exponent -= zeroCount;
for (i = 0; i < ln->digitCount; i++)
{ // shift them
ln->array[i] = ln->array[i + zeroCount];
} // shift them
} // digits to shift
} // found leading zeroes
// handle railing zeroes
i = ln->digitCount - 1;
while ((i >= 0) && (0 == ln->array[i]))
{ // while
ln->digitCount--;
i--;
} // while
if (0 == ln->digitCount)
{ // entire number is zero
ln->exponent = 0;
ln->sign = 1;
} // entire number is zero
} // digits to process
return (errorLevel);
} // END function LNnormalize -- (200302)
int LNadd(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
LARGE_NUMBER_STRUCT *ln3)
// ln3=ln1+ln2
{ // BEGIN function LNadd -- (200302)
int i, cnt, state = 0, carry = 0;
LARGE_NUMBER_STRUCT ln1, ln2;
if (0 == lna->digitCount)
*ln3 = *lnb;
else
if (0 == lnb->digitCount)
*ln3 = *lna;
else
{ // add non-zero numbers
ln1 = *lna;
ln2 = *lnb;
if (ln1.sign != ln2.sign)
{ // signs different
LNnegate(&ln2);
state = LNsubtract(&ln1, &ln2, ln3);
} // signs different
else
{ // signs are same -- continue adding
if (ln1.exponent > ln2.exponent)
{ // ln1 is biger
LNshift(&ln1, 1);
LNshift(&ln2, (ln1.exponent - ln2.exponent));
} // ln1 is biger
else
{ // ln2 is biger
LNshift(&ln2, 1);
LNshift(&ln1, (ln2.exponent - ln1.exponent));
} // ln2 is biger
if (ln1.digitCount > ln2.digitCount)
{ // 1 has more digits
for (i = ln1.digitCount - 1; i >= ln2.digitCount; i--)
ln3->array[i] = ln1.array[i];
cnt = ln2.digitCount;
ln3->digitCount = ln1.digitCount;
} // 1 has more digits
else
{ // 2 has more digits
for (i = ln2.digitCount - 1; i >= ln1.digitCount; i--)
ln3->array[i] = ln2.array[i];
cnt = ln1.digitCount;
ln3->digitCount = ln2.digitCount;
} // 2 has more digits
// now actually add
ln3->exponent = ln1.exponent;
for (i = cnt - 1; i >= 0; i--)
{ // for
ln3->array[i] = ln1.array[i] + ln2.array[i] + carry;
if (ln3->array[i] > 9)
{ // set carry
carry = 1;
ln3->array[i] -= 10;
} // set carry
else
{ // reset carry
carry = 0;
} // reset carry
} // for
LNnormalize(ln3);
} // signs are same -- continue adding
} // add non-zero numbers
return state;
} // END function LNadd -- (200302)
int LNsubtract(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
LARGE_NUMBER_STRUCT *ln3)
// ln3=ln1-ln2
{ // BEGIN function LNsubtract -- (200303)
int toReturn = 0;
LARGE_NUMBER_STRUCT ln1, ln2;
ln1 = *lna;
ln2 = *lnb;
if (0 == lna->digitCount)
{ // first number is zero
*ln3 = *lnb;
LNnegate(ln3);
} // first number is zero
else
if (0 == lnb->digitCount)
*ln3 = *lna;
else
{ // subtract non-zero numbers
if (ln1.sign != ln2.sign)
{ // signs different
LNnegate(&ln2);
toReturn = LNadd(&ln1, &ln2, ln3);
} // signs different
else
{ // signs are same - so subtract
int t, i, tmp, borrow = 0;
t = LNcompare(&ln1, &ln2);
if (0 == t)
{ // same number - return 9
ln3->sign = 1;
ln3->exponent = 0;
ln3->digitCount = 0;
} // same number - return 9
else
if (0 > t)
{ // first number smaller
toReturn = LNsubtract(&ln2, &ln1, ln3);
ln3->sign = -1 * ln3->sign;
} // first number smaller
else
{ // everything okay - actually subtract
ln3->sign = ln1.sign;
ln3->exponent = ln1.exponent;
LNshift(&ln2, (ln1.exponent - ln2.exponent));
if (ln1.digitCount != ln2.digitCount)
if (ln1.digitCount > ln2.digitCount)
{ // add zeroes to ln2
for (i=ln2.digitCount; i < ln1.digitCount; i++)
ln2.array[i] = 0;
ln2.digitCount = ln1.digitCount;
} // add zeroes to ln2
else
{ // add zeroes to ln1
for (i=ln1.digitCount; i < ln2.digitCount; i++)
ln1.array[i] = 0;
ln1.digitCount = ln2.digitCount;
} // add zeroes to ln1
for (i = ln1.digitCount - 1; i >= 0; i--)
{ // loop through each digit
tmp = borrow + ln2.array[i];
if (ln1.array[i] > tmp)
{ // no borrow
ln3->array[i] = ln1.array[i] - tmp;
borrow = 0;
} // no borrow
else
{ // have to borrow
ln3->array[i] = (10 + ln1.array[i]) - tmp;
borrow = 1;
} // have to borrow
} // loop through each digit
LNnormalize(ln3);
} // everything okay - actually subtract
} // signs are same - so subtract
} // subtract non-zero numbers
return toReturn;
} // END function LNsubtract -- (200303)
int LNmultiply(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2,
LARGE_NUMBER_STRUCT *ln3)
// ln3=ln1*ln2
{ // BEGIN function LNmultiply -- (200303)
if ((0 == ln1->digitCount) || (0 == ln2->digitCount))
{ // multiply by 0 and get 0
ln3->digitCount = 0;
ln3->sign = 0;
ln3->exponent = 0;
ln3->array[0] = 0;
} // multiply by 0 and get 0
else
{ // guess we have to multiply
int i1, i2, i3, dig, tmp, carry;
ln3->sign = ln1->sign * ln2->sign;
ln3->exponent = ln1->exponent + ln2->exponent;
ln3->digitCount = ln1->digitCount + ln2->digitCount;
dig = ln3->digitCount - 1;
// zero out ln3 so that it can be summed into
for (i3=0; i3 <= dig; i3++)
ln3->array[i3] = 0;
for (i2=ln2->digitCount - 1; i2 >= 0; i2--)
{ // loop through the second numbers digits
carry = 0;
i3 = dig--;
for (i1=ln1->digitCount - 1; i1 >= 0; i1--)
{ // process first number
tmp = (ln1->array[i1] * ln2->array[i2]) + carry + ln3->array[i3];
if (tmp > 9)
{ // deal with overflow
carry = tmp / 10;
ln3->array[i3] = (tmp % 10);
} // deal with overflow
else
{ // no overflow
carry = 0;
ln3->array[i3] = tmp;
} // no overflow
i3--;
} // process first number
ln3->array[i3] = ln3->array[i3] + carry;
} // loop through the second numbers digits
LNnormalize(ln3);
} // guess we have to multiply
return 0;
} // END function LNmultiply -- (200303)
int LNdivide(LARGE_NUMBER_STRUCT *ln1, long int i2, LARGE_NUMBER_STRUCT *ln3)
// ln3=ln1/i2
{ // BEGIN function LNdivide -- (200303)
int i, tot = 0;
ln3->exponent = ln1->exponent;
ln3->sign = ln1->sign * ((0 < i2) ? 1 : -1);
for (i=0; i < ln1->digitCount; i++)
{ // for each digit
tot += ln1->array[i];
if (tot >= i2)
{ // we can divide
ln3->array[i] = tot / i2;
tot = (tot % i2) * 10;
} // we can divide
else
{ // can't divide yet, so add a zero
ln3->array[i] = 0;
tot *= 10;
} // can't divide yet, so add a zero
} // for each digit
ln3->digitCount = i;
while ((LN_MAX_DIGITS > ln3->digitCount) && (0 < tot))
{ // add zeroes on right
if (tot >= i2)
{ // we can divide
ln3->array[ln3->digitCount] = tot / i2;
tot = (tot % i2) * 10;
} // we can divide
else
{ // can't divide yet, so add a zero
ln3->array[ln3->digitCount] = 0;
tot *= 10;
} // can't divide yet, so add a zero
ln3->digitCount++;
} // add zeroes on right
LNnormalize(ln3);
return 0;
} // END function LNdivide -- (200303)
int LNdcnvrt(double d, LARGE_NUMBER_STRUCT *n)
// convert a double to Large Number
{ // BEGIN function LNdcnvrt -- (200303)
char str[LN_MAX_DIGITS];
sprintf(str, "%ld:", d);
return LNstr2arr(str, n);
} // END function LNdcnvrt -- (200303)
int LNcopy(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2)
// copy from ln1 to ln2
{ // BEGIN function LNcopy -- (200302)
int i;
ln2->sign = ln1->sign;
ln2->exponent = ln1->exponent;
ln2->digitCount = ln1->digitCount;
for (i=0; i < ln1->digitCount; i++)
ln2->array[i] = ln1->array[i];
return 0;
} // END function LNcopy -- (200302)
#include <stdio.h>
#define DEBUG1 (1 != 1)
#include "LargeNumber.c"
int main ()
{ /* begin FUNCTION main */
int i;
LARGE_NUMBER_STRUCT a;
LARGE_NUMBER_STRUCT b;
LARGE_NUMBER_STRUCT c;
int res;
long int ii;
char num[1000];
char tmp[1000];
ii = 123456789;
if (DEBUG1) printf ("A\n");
res = LNicnvrt(ii, &a);
printf("------- Display Test ----------\n");
LNarr2strExp(&a, num);
printf("LNarr2strExp(a)=%s\n",num);
LNarr2strInt(&a, num);
printf("LNarr2strInt(a)=%s\n",num);
LNln2strFloat(&a, num);
printf("LNln2strFloat(a)=%s\n",num);
LNprint(&a);
printf("-------------------------------\n");
printf("------- Multiply Test ---------\n");
LNicnvrt(123, &a);
LNicnvrt(12, &b);
LNmultiply(&a, &b, &c);
LNarr2strInt(&a, num);
printf("a(%s) * ", num);
LNarr2strInt(&b, num);
printf("b(%s) ", num);
LNarr2strInt(&c, num);
printf(" = c(%s)\n", num);
printf("\n");
printf("-------------------------------\n");
printf("------- Divide Test ---------\n");
LNicnvrt(1224, &a);
LNdivide(&a, 12, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 12 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
printf("\n");
LNicnvrt(12, &a);
LNdivide(&a, 12, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 12 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
printf("\n");
LNicnvrt(1, &a);
LNdivide(&a, 1, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 1 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
printf("\n");
LNicnvrt(1, &a);
LNdivide(&a, 12, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 12 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
printf("\n");
LNicnvrt(1, &a);
LNdivide(&a, 125, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 125 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
for (i=100000; i > 0; i = i / 10) {
LNstr2arr("1111.111111111", &a);
LNdivide(&a, i, &c);
LNarr2strInt(&a, num);
printf("a(%s) / %d ", num, i);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num); }
tmp = "0.000000000000000000000000000000000000000000000";
strcat(tmp, "0000000000000000000000000001111111111111");
LNstr2arr(tmp, &a);
LNdivide(&a, 10, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 10 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
tmp ="30765988567369.34938637363858653405834085348673";
strcat(tmp, "4086334739573957397534757357345973497375");
strcat(tmp, "734573453957");
LNstr2arr(tmp, &a);
LNdivide(&a, 123456789, &c);
LNarr2strInt(&a, num);
printf("a(%s) / 123456789 ", num);
LNarr2strExp(&c, num);
printf(" = c(%s)\n", num);
printf("\n");
printf("-------------------------------\n");
LNicnvrt(123, &a);
if (DEBUG1) printf ("B\n");
printf("\n");
printf("-------------------------------\n");
LNicnvrt(123, &a);
if (DEBUG1) printf ("B\n");
res = LNcopy(&a,&b);
b.array[b.exponent] = 3;
if (DEBUG1) printf ("C\n");
LNprint(&a);
printf("%d - %d\n",a.exponent,a.digitCount);
LNprint(&b);
printf("%d - %d\n",b.exponent,b.digitCount);
if (DEBUG1) printf ("D\n");
a.array[0] = 2;
LNarr2strExp(&a, num);
printf("arr2str: [%s]\n", num);
a.array[0] = 3;
LNarr2strExp(&a, num);
printf("ln2strExp: [%s]\n", num);
a.array[0] = 4;
LNarr2strInt(&a, num);
printf("ln2strInt: [%s]\n", num);
a.array[0] = 5;
a.exponent = 3;
LNarr2strInt(&a, num);
printf("ln2strInt: [%s]\n", num);
a.array[0] = 6;
a.exponent = 15;
LNarr2strInt(&a, num);
printf("ln2strInt: [%s]\n", num);
a.array[0] = 7;
a.exponent = 7;
LNln2strFloat(&a, num);
printf("ln2strFloat: [%s]\n", num);
LNadd(&a, &b, &c);
LNarr2strExp(&a, num);
printf("[%s] + ", num);
LNarr2strExp(&b, num);
printf("[%s] = ", num);
LNarr2strExp(&c, num);
printf("[%s]\n", num);
LNsubtract(&a, &b, &c);
LNarr2strExp(&a, num);
printf("[%s] - ", num);
LNarr2strExp(&b, num);
printf("[%s] = ", num);
LNarr2strExp(&c, num);
printf("[%s]\n", num);
LNsubtract(&b, &a, &c);
LNarr2strExp(&b, num);
printf("[%s] - ", num);
LNarr2strExp(&a, num);
printf("[%s] = ", num);
LNarr2strExp(&c, num);
printf("[%s]\n", num);
} /* end FUNCTION main */
#include <ctype.h>
#define LN_MAX_DIGITS 1000
typedef struct LARGE_NUMBER_STRUCT
{
unsigned short int array[LN_MAX_DIGITS];
signed short int sign;
signed long int exponent;
signed short int digitCount;
}
LARGE_NUMBER_STRUCT;
void LNprint(LARGE_NUMBER_STRUCT *n)
{
char str[LN_MAX_DIGITS+25];
LNarr2strExp(n, str);
printf("[%s]\n", str);
}
int LNnegate(LARGE_NUMBER_STRUCT *ln1)
{
if (0 != ln1->digitCount)
ln1->sign *= -1;
return 0;
}
int LNcompare(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2)
{
int toReturn = 0;
if (ln1->sign ^ ln2->sign)
{
toReturn = (0 > ln1->sign) ? -1 : 1;
}
else
{
if (ln1->exponent != ln2->exponent)
{
toReturn = (ln1->exponent > ln2->exponent) ? 1 : -1;
}
else
{
int i, t;
t = (ln1->digitCount > ln2->digitCount) ? ln2->digitCount : ln1->digitCount;
for (i=0; (i<t) && (0 == toReturn) ; i++)
{
if (ln1->array[i] != ln2->array[i])
toReturn = (ln1->array[i] > ln2->array[i]) ? ln1->sign : - ln2->sign;
}
if ((0 == toReturn) && (ln1->digitCount != ln2->digitCount))
toReturn = (ln1->digitCount > ln2->digitCount) ? ln1->sign : - ln2->sign;
}
}
return toReturn;
}
int LNstr2arr(char str[], LARGE_NUMBER_STRUCT *ln)
{
#define START 1
#define NUM1 2
#define NUM2 3
#define DEC1 4
#define DEC2 5
#define EXP1 6
#define EXP2 7
#define EXP3 8
int state = START, done = 0, n = 0;
signed short int dpflag = 0, numflag = 0, sign = 1;
signed long int exp;
char *ch = str;
while ( (isspace(*ch)) || ('0' == *ch) ) ch++;
if (0 != *ch)
{
if ('-' == *ch)
{
sign = -1;
ch++;
}
else
if (*ch == '+')
{
ch++;
}
while (isdigit(*ch))
{
state = NUM2;
ln->array[n++] = *ch - '0';
ch++;
}
exp = n;
if ('.' == *ch)
{
state = (NUM2 != state) ? DEC1 : DEC2;
ch++;
if (isdigit(*ch)) state = DEC2;
while (isdigit(*ch))
{
ln->array[n++] = *ch - '0';
ch++;
}
}
if (('E' == *ch) || ('e' == *ch))
{
signed long int texp;
state = EXP2;
ch++;
sscanf(ch, "%d", &texp);
exp += texp;
}
}
if ((EXP2 == state) || (DEC2 == state) || (NUM2 == state))
{
ln->sign = sign;
ln->exponent = exp;
ln->digitCount = n;
state = 0;
}
return state;
}
int LNicnvrt(long int number, LARGE_NUMBER_STRUCT *n)
{
int idx, digit, j;
n->sign = (number < 0) ? -1 : 1;
n->exponent = 0;
idx = LN_MAX_DIGITS;
while (number > 0)
{
digit = number % 10;
n->array[--idx] = digit;
number /= 10;
}
n->exponent = LN_MAX_DIGITS - idx;
n->digitCount = n->exponent;
for (j=0; LN_MAX_DIGITS > (j + idx); j++)
{
n->array[j] = n->array[idx+j];
}
return 0;
}
int LNarr2strExp(LARGE_NUMBER_STRUCT *ln, char str[])
{
int i, cnt = 0;
if (0 == ln->digitCount)
{
strncpy("+0E0", str);
}
else
{
str[cnt++] = (0 > ln->sign) ? '-' : '+';
str[cnt++] = '0' + ln->array[0];
str[cnt++] = '.';
for (i = 1; i < ln->digitCount; i++)
str[cnt++] = '0' + ln->array[i];
str[cnt++] = 'E';
sprintf(&(str[cnt]), "%+ld", (ln->exponent-1));
}
return 0;
}
int LNarr2strInt(LARGE_NUMBER_STRUCT *ln, char str[])
{
int i, cnt = 0;
if ((0 > ln->exponent) || (0 >= ln->digitCount))
{
strncpy("+0", str);
}
else
{
int x;
str[cnt++] = (0 > ln->sign) ? '-' : '+';
x = (ln->exponent > ln->digitCount) ? ln->digitCount : ln->exponent;
for (i = 0; i < x; i++)
str[cnt++] = '0' + ln->array[i];
x = ln->exponent - ln->digitCount;
for (i=0; i < x; i++)
str[cnt++] = '0';
str[cnt] = 0;
}
return 0;
}
int LNln2strFloat(LARGE_NUMBER_STRUCT *ln, char str[])
{
int i, cnt = 0;
if (0 == ln->digitCount)
{
strncpy("+0.0", str);
}
else
{
int x1, x2;
str[cnt++] = (0 > ln->sign) ? '-' : '+';
x1 = (ln->exponent > ln->digitCount) ? ln->digitCount : ln->exponent;
for (i = 0; i < x1; i++)
str[cnt++] = '0' + ln->array[i];
x2 = ln->exponent - ln->digitCount;
if (0 > x2)
{
str[cnt++] = '.';
for (i = x1; i < ln->digitCount; i++)
str[cnt++] = '0' + ln->array[i];
}
else
{
for (i=0; i < x2; i++)
str[cnt++] = '0';
str[cnt++] = '.';
str[cnt++] = '0';
}
str[cnt++] = 0;
}
return 0;
}
int LNshift(LARGE_NUMBER_STRUCT *ln, int cnt)
{
int i, errorLevel = 0;
if (0 < ln->digitCount)
if (0 < cnt)
{
for ((i = ln->digitCount - 1); i >= 0 ; i --)
ln->array[i + cnt] = ln->array[i];
for (i = 0; i < cnt; i ++)
ln->array[i] = 0;
ln->exponent += cnt;
ln->digitCount += cnt;
}
else
if (0 != cnt)
{
fprintf (stderr, "Error: Cannot shift negative bits.\n");
errorLevel = 1;
}
return errorLevel;
}
int LNnormalize(LARGE_NUMBER_STRUCT *ln)
{
int i, errorLevel = 0, zeroCount = 0;
if (0 < ln->digitCount)
{
while ((ln->array[zeroCount] == 0) && (zeroCount < ln->digitCount))
{
zeroCount ++;
}
if (0 < zeroCount)
{
if (zeroCount == ln->digitCount)
{
ln->exponent = 0;
ln->digitCount = 0;
ln->sign = 1;
}
else
{
ln->digitCount -= zeroCount;
ln->exponent -= zeroCount;
for (i = 0; i < ln->digitCount; i++)
{
ln->array[i] = ln->array[i + zeroCount];
}
}
}
i = ln->digitCount - 1;
while ((i >= 0) && (0 == ln->array[i]))
{
ln->digitCount--;
i--;
}
if (0 == ln->digitCount)
{
ln->exponent = 0;
ln->sign = 1;
}
}
return (errorLevel);
}
int LNadd(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
LARGE_NUMBER_STRUCT *ln3)
{
int i, cnt, state = 0, carry = 0;
LARGE_NUMBER_STRUCT ln1, ln2;
if (0 == lna->digitCount)
*ln3 = *lnb;
else
if (0 == lnb->digitCount)
*ln3 = *lna;
else
{
ln1 = *lna;
ln2 = *lnb;
if (ln1.sign != ln2.sign)
{
LNnegate(&ln2);
state = LNsubtract(&ln1, &ln2, ln3);
}
else
{
if (ln1.exponent > ln2.exponent)
{
LNshift(&ln1, 1);
LNshift(&ln2, (ln1.exponent - ln2.exponent));
}
else
{
LNshift(&ln2, 1);
LNshift(&ln1, (ln2.exponent - ln1.exponent));
}
if (ln1.digitCount > ln2.digitCount)
{
for (i = ln1.digitCount - 1; i >= ln2.digitCount; i--)
ln3->array[i] = ln1.array[i];
cnt = ln2.digitCount;
ln3->digitCount = ln1.digitCount;
}
else
{
for (i = ln2.digitCount - 1; i >= ln1.digitCount; i--)
ln3->array[i] = ln2.array[i];
cnt = ln1.digitCount;
ln3->digitCount = ln2.digitCount;
}
ln3->exponent = ln1.exponent;
for (i = cnt - 1; i >= 0; i--)
{
ln3->array[i] = ln1.array[i] + ln2.array[i] + carry;
if (ln3->array[i] > 9)
{
carry = 1;
ln3->array[i] -= 10;
}
else
{
carry = 0;
}
}
LNnormalize(ln3);
}
}
return state;
}
int LNsubtract(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
LARGE_NUMBER_STRUCT *ln3)
{
int toReturn = 0;
LARGE_NUMBER_STRUCT ln1, ln2;
ln1 = *lna;
ln2 = *lnb;
if (0 == lna->digitCount)
{
*ln3 = *lnb;
LNnegate(ln3);
}
else
if (0 == lnb->digitCount)
*ln3 = *lna;
else
{
if (ln1.sign != ln2.sign)
{
LNnegate(&ln2);
toReturn = LNadd(&ln1, &ln2, ln3);
}
else
{
int t, i, tmp, borrow = 0;
t = LNcompare(&ln1, &ln2);
if (0 == t)
{
ln3->sign = 1;
ln3->exponent = 0;
ln3->digitCount = 0;
}
else
if (0 > t)
{
toReturn = LNsubtract(&ln2, &ln1, ln3);
ln3->sign = -1 * ln3->sign;
}
else
{
ln3->sign = ln1.sign;
ln3->exponent = ln1.exponent;
LNshift(&ln2, (ln1.exponent - ln2.exponent));
if (ln1.digitCount != ln2.digitCount)
if (ln1.digitCount > ln2.digitCount)
{
for (i=ln2.digitCount; i < ln1.digitCount; i++)
ln2.array[i] = 0;
ln2.digitCount = ln1.digitCount;
}
else
{
for (i=ln1.digitCount; i < ln2.digitCount; i++)
ln1.array[i] = 0;
ln1.digitCount = ln2.digitCount;
}
for (i = ln1.digitCount - 1; i >= 0; i--)
{
tmp = borrow + ln2.array[i];
if (ln1.array[i] > tmp)
{
ln3->array[i] = ln1.array[i] - tmp;
borrow = 0;
}
else
{
ln3->array[i] = (10 + ln1.array[i]) - tmp;
borrow = 1;
}
}
LNnormalize(ln3);
}
}
}
return toReturn;
}
int LNmultiply(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2,
LARGE_NUMBER_STRUCT *ln3)
{
if ((0 == ln1->digitCount) || (0 == ln2->digitCount))
{
ln3->digitCount = 0;
ln3->sign = 0;
ln3->exponent = 0;
ln3->array[0] = 0;
}
else
{
int i1, i2, i3, dig, tmp, carry;
ln3->sign = ln1->sign * ln2->sign;
ln3->exponent = ln1->exponent + ln2->exponent;
ln3->digitCount = ln1->digitCount + ln2->digitCount;
dig = ln3->digitCount - 1;
for (i3=0; i3 <= dig; i3++)
ln3->array[i3] = 0;
for (i2=ln2->digitCount - 1; i2 >= 0; i2--)
{
carry = 0;
i3 = dig--;
for (i1=ln1->digitCount - 1; i1 >= 0; i1--)
{
tmp = (ln1->array[i1] * ln2->array[i2]) + carry + ln3->array[i3];
if (tmp > 9)
{
carry = tmp / 10;
ln3->array[i3] = (tmp % 10);
}
else
{
carry = 0;
ln3->array[i3] = tmp;
}
i3--;
}
ln3->array[i3] = ln3->array[i3] + carry;
}
LNnormalize(ln3);
}
return 0;
}
int LNdivide(LARGE_NUMBER_STRUCT *ln1, long int i2, LARGE_NUMBER_STRUCT *ln3)
{
int i, tot = 0;
ln3->exponent = ln1->exponent;
ln3->sign = ln1->sign * ((0 < i2) ? 1 : -1);
for (i=0; i < ln1->digitCount; i++)
{
tot += ln1->array[i];
if (tot >= i2)
{
ln3->array[i] = tot / i2;
tot = (tot % i2) * 10;
}
else
{
ln3->array[i] = 0;
tot *= 10;
}
}
ln3->digitCount = i;
while ((LN_MAX_DIGITS > ln3->digitCount) && (0 < tot))
{
if (tot >= i2)
{
ln3->array[ln3->digitCount] = tot / i2;
tot = (tot % i2) * 10;
}
else
{
ln3->array[ln3->digitCount] = 0;
tot *= 10;
}
ln3->digitCount++;
}
LNnormalize(ln3);
return 0;
}
int LNdcnvrt(double d, LARGE_NUMBER_STRUCT *n)
{
char str[LN_MAX_DIGITS];
sprintf(str, "%ld:", d);
return LNstr2arr(str, n);
}
int LNcopy(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2)
{
int i;
ln2->sign = ln1->sign;
ln2->exponent = ln1->exponent;
ln2->digitCount = ln1->digitCount;
for (i=0; i < ln1->digitCount; i++)
ln2->array[i] = ln1->array[i];
return 0;
}
#include <ctype.h>
#define LMD 1000
typedef struct LNS
{
unsigned short int a[LMD];
signed short int sign;
signed long int exp;
signed short int dc;
}
LNS;
void LNprint(LNS *n)
{
char str[LMD+25];
LNarr2strExp(n, str);
printf("[%s]\n", str);
}
int LNnegate(LNS *ln1)
{
if (0 != ln1->dc)
ln1->sign *= -1;
return 0;
}
int LNcompare(LNS *ln1, LNS *ln2)
{
int ret = 0;
if (ln1->sign ^ ln2->sign)
{
ret = (0 > ln1->sign) ? -1 : 1;
}
else
{
if (ln1->exp != ln2->exp)
{
ret = (ln1->exp > ln2->exp) ? 1 : -1;
}
else
{
int i, t;
t = (ln1->dc > ln2->dc) ? ln2->dc : ln1->dc;
for (i=0; (i<t) && (0 == ret) ; i++)
{
if (ln1->a[i] != ln2->a[i])
ret = (ln1->a[i] > ln2->a[i]) ? ln1->sign : - ln2->sign;
}
if ((0 == ret) && (ln1->dc != ln2->dc))
ret = (ln1->dc > ln2->dc) ? ln1->sign : - ln2->sign;
}
}
return ret;
}
int LNstr2arr(char str[], LNS *ln)
{
#define START 1
#define NUM1 2
#define NUM2 3
#define DEC1 4
#define DEC2 5
#define EXP1 6
#define EXP2 7
#define EXP3 8
int state = START, done = 0, n = 0;
signed short int dpflag = 0, numflag = 0, sign = 1;
signed long int exp;
char *ch = str;
while ( (isspace(*ch)) || ('0' == *ch) ) ch++;
if (0 != *ch)
{
if ('-' == *ch)
{
sign = -1;
ch++;
}
else
if (*ch == '+')
{
ch++;
}
while (isdigit(*ch))
{
state = NUM2;
ln->a[n++] = *ch - '0';
ch++;
}
exp = n;
if ('.' == *ch)
{
state = (NUM2 != state) ? DEC1 : DEC2;
ch++;
if (isdigit(*ch)) state = DEC2;
while (isdigit(*ch))
{
ln->a[n++] = *ch - '0';
ch++;
}
}
if (('E' == *ch) || ('e' == *ch))
{
signed long int texp;
state = EXP2;
ch++;
sscanf(ch, "%d", &texp);
exp += texp;
}
}
if ((EXP2 == state) || (DEC2 == state) || (NUM2 == state))
{
ln->sign = sign;
ln->exp = exp;
ln->dc = n;
state = 0;
}
return state;
}
int LNicnvrt(long int number, LNS *n)
{
int idx, digit, j;
n->sign = (number < 0) ? -1 : 1;
n->exp = 0;
idx = LMD;
while (number > 0)
{
digit = number % 10;
n->a[--idx] = digit;
number /= 10;
}
n->exp = LMD - idx;
n->dc = n->exp;
for (j=0; LMD > (j + idx); j++)
{
n->a[j] = n->a[idx+j];
}
return 0;
}
int LNarr2strExp(LNS *ln, char str[])
{
int i, cnt = 0;
if (0 == ln->dc)
{
strncpy("+0E0", str);
}
else
{
str[cnt++] = (0 > ln->sign) ? '-' : '+';
str[cnt++] = '0' + ln->a[0];
str[cnt++] = '.';
for (i = 1; i < ln->dc; i++)
str[cnt++] = '0' + ln->a[i];
str[cnt++] = 'E';
sprintf(&(str[cnt]), "%+ld", (ln->exp-1));
}
return 0;
}
int LNarr2strInt(LNS *ln, char str[])
{
int i, cnt = 0;
if ((0 > ln->exp) || (0 >= ln->dc))
{
strncpy("+0", str);
}
else
{
int x;
str[cnt++] = (0 > ln->sign) ? '-' : '+';
x = (ln->exp > ln->dc) ? ln->dc : ln->exp;
for (i = 0; i < x; i++)
str[cnt++] = '0' + ln->a[i];
x = ln->exp - ln->dc;
for (i=0; i < x; i++)
str[cnt++] = '0';
str[cnt] = 0;
}
return 0;
}
int LNln2strFloat(LNS *ln, char str[])
{
int i, cnt = 0;
if (0 == ln->dc)
{
strncpy("+0.0", str);
}
else
{
int x1, x2;
str[cnt++] = (0 > ln->sign) ? '-' : '+';
x1 = (ln->exp > ln->dc) ? ln->dc : ln->exp;
for (i = 0; i < x1; i++)
str[cnt++] = '0' + ln->a[i];
x2 = ln->exp - ln->dc;
if (0 > x2)
{
str[cnt++] = '.';
for (i = x1; i < ln->dc; i++)
str[cnt++] = '0' + ln->a[i];
}
else
{
for (i=0; i < x2; i++)
str[cnt++] = '0';
str[cnt++] = '.';
str[cnt++] = '0';
}
str[cnt++] = 0;
}
return 0;
}
int LNshift(LNS *ln, int cnt)
{
int i, errorLevel = 0;
if (0 < ln->dc)
if (0 < cnt)
{
for ((i = ln->dc - 1); i >= 0 ; i --)
ln->a[i + cnt] = ln->a[i];
for (i = 0; i < cnt; i ++)
ln->a[i] = 0;
ln->exp += cnt;
ln->dc += cnt;
}
else
if (0 != cnt)
{
fprintf (stderr, "Error: Cannot shift negative bits.\n");
errorLevel = 1;
}
return errorLevel;
}
int LNnormalize(LNS *ln)
{
int i, errorLevel = 0, zeroCount = 0;
if (0 < ln->dc)
{
while ((ln->a[zeroCount] == 0) && (zeroCount < ln->dc))
{
zeroCount ++;
}
if (0 < zeroCount)
{
if (zeroCount == ln->dc)
{
ln->exp = 0;
ln->dc = 0;
ln->sign = 1;
}
else
{
ln->dc -= zeroCount;
ln->exp -= zeroCount;
for (i = 0; i < ln->dc; i++)
{
ln->a[i] = ln->a[i + zeroCount];
}
}
}
i = ln->dc - 1;
while ((i >= 0) && (0 == ln->a[i]))
{
ln->dc--;
i--;
}
if (0 == ln->dc)
{
ln->exp = 0;
ln->sign = 1;
}
}
return (errorLevel);
}
int LNadd(LNS *lna, LNS *lnb,
LNS *ln3)
{
int i, cnt, state = 0, carry = 0;
LNS ln1, ln2;
if (0 == lna->dc)
*ln3 = *lnb;
else
if (0 == lnb->dc)
*ln3 = *lna;
else
{
ln1 = *lna;
ln2 = *lnb;
if (ln1.sign != ln2.sign)
{
LNnegate(&ln2);
state = LNsubtract(&ln1, &ln2, ln3);
}
else
{
if (ln1.exp > ln2.exp)
{
LNshift(&ln1, 1);
LNshift(&ln2, (ln1.exp - ln2.exp));
}
else
{
LNshift(&ln2, 1);
LNshift(&ln1, (ln2.exp - ln1.exp));
}
if (ln1.dc > ln2.dc)
{
for (i = ln1.dc - 1; i >= ln2.dc; i--)
ln3->a[i] = ln1.a[i];
cnt = ln2.dc;
ln3->dc = ln1.dc;
}
else
{
for (i = ln2.dc - 1; i >= ln1.dc; i--)
ln3->a[i] = ln2.a[i];
cnt = ln1.dc;
ln3->dc = ln2.dc;
}
ln3->exp = ln1.exp;
for (i = cnt - 1; i >= 0; i--)
{
ln3->a[i] = ln1.a[i] + ln2.a[i] + carry;
if (ln3->a[i] > 9)
{
carry = 1;
ln3->a[i] -= 10;
}
else
{
carry = 0;
}
}
LNnormalize(ln3);
}
}
return state;
}
int LNsubtract(LNS *lna, LNS *lnb,
LNS *ln3)
{
int ret = 0;
LNS ln1, ln2;
ln1 = *lna;
ln2 = *lnb;
if (0 == lna->dc)
{
*ln3 = *lnb;
LNnegate(ln3);
}
else
if (0 == lnb->dc)
*ln3 = *lna;
else
{
if (ln1.sign != ln2.sign)
{
LNnegate(&ln2);
ret = LNadd(&ln1, &ln2, ln3);
}
else
{
int t, i, tmp, borrow = 0;
t = LNcompare(&ln1, &ln2);
if (0 == t)
{
ln3->sign = 1;
ln3->exp = 0;
ln3->dc = 0;
}
else
if (0 > t)
{
ret = LNsubtract(&ln2, &ln1, ln3);
ln3->sign = -1 * ln3->sign;
}
else
{
ln3->sign = ln1.sign;
ln3->exp = ln1.exp;
LNshift(&ln2, (ln1.exp - ln2.exp));
if (ln1.dc != ln2.dc)
if (ln1.dc > ln2.dc)
{
for (i=ln2.dc; i < ln1.dc; i++)
ln2.a[i] = 0;
ln2.dc = ln1.dc;
}
else
{
for (i=ln1.dc; i < ln2.dc; i++)
ln1.a[i] = 0;
ln1.dc = ln2.dc;
}
for (i = ln1.dc - 1; i >= 0; i--)
{
tmp = borrow + ln2.a[i];
if (ln1.a[i] > tmp)
{
ln3->a[i] = ln1.a[i] - tmp;
borrow = 0;
}
else
{
ln3->a[i] = (10 + ln1.a[i]) - tmp;
borrow = 1;
}
}
LNnormalize(ln3);
}
}
}
return ret;
}
int LNmultiply(LNS *ln1, LNS *ln2,
LNS *ln3)
{
if ((0 == ln1->dc) || (0 == ln2->dc))
{
ln3->dc = 0;
ln3->sign = 0;
ln3->exp = 0;
ln3->a[0] = 0;
}
else
{
int i1, i2, i3, dig, tmp, carry;
ln3->sign = ln1->sign * ln2->sign;
ln3->exp = ln1->exp + ln2->exp;
ln3->dc = ln1->dc + ln2->dc;
dig = ln3->dc - 1;
for (i3=0; i3 <= dig; i3++)
ln3->a[i3] = 0;
for (i2=ln2->dc - 1; i2 >= 0; i2--)
{
carry = 0;
i3 = dig--;
for (i1=ln1->dc - 1; i1 >= 0; i1--)
{
tmp = (ln1->a[i1] * ln2->a[i2]) + carry + ln3->a[i3];
if (tmp > 9)
{
carry = tmp / 10;
ln3->a[i3] = (tmp % 10);
}
else
{
carry = 0;
ln3->a[i3] = tmp;
}
i3--;
}
ln3->a[i3] = ln3->a[i3] + carry;
}
LNnormalize(ln3);
}
return 0;
}
int LNdivide(LNS *ln1, long int i2, LNS *ln3)
{
int i, tot = 0;
ln3->exp = ln1->exp;
ln3->sign = ln1->sign * ((0 < i2) ? 1 : -1);
for (i=0; i < ln1->dc; i++)
{
tot += ln1->a[i];
if (tot >= i2)
{
ln3->a[i] = tot / i2;
tot = (tot % i2) * 10;
}
else
{
ln3->a[i] = 0;
tot *= 10;
}
}
ln3->dc = i;
while ((LMD > ln3->dc) && (0 < tot))
{
if (tot >= i2)
{
ln3->a[ln3->dc] = tot / i2;
tot = (tot % i2) * 10;
}
else
{
ln3->a[ln3->dc] = 0;
tot *= 10;
}
ln3->dc++;
}
LNnormalize(ln3);
return 0;
}
int LNdcnvrt(double d, LNS *n)
{
char str[LMD];
sprintf(str, "%ld:", d);
return LNstr2arr(str, n);
}
int LNcopy(LNS *ln1, LNS *ln2)
{
int i;
ln2->sign = ln1->sign;
ln2->exp = ln1->exp;
ln2->dc = ln1->dc;
for (i=0; i < ln1->dc; i++)
ln2->a[i] = ln1->a[i];
return 0;
}
The statements and opinions included in these pages are those of only. Any statements and
opinions included in these pages are not those of Louisiana
State University or the LSU Board of Supervisors.
© 1999, 2000, 2001, 2002, 2003 Isaac Traxler