note, I have compiled it under GCC (4.5)
//BigInteger.h
#ifndef BIG_INTEGER_H
#define BIG_INTEGER_H
typedef struct {
char *data;
size_t length;
short sign; // 0 for positive (default value), otherwise for negative
} BigInteger;
// BigInteger interface functions
/**
* The char array are provided from right to left, for example if you want to reprensent the number 200, you
* should use array looks like:
* char arr[] = {0, 0, 2};
*/
BigInteger* construct(char[], size_t);
BigInteger* add(BigInteger*, BigInteger*);
BigInteger* subtract(BigInteger*, BigInteger*);
char* get(BigInteger*);
void print(BigInteger*);
// utility functions
static void intcpy(char*, char*, int);
static char** get_adjusted(BigInteger*, BigInteger*);
#endif
//BigInteger.c
#include <stdio.h>
#include <stdlib.h>
#include "BigInteger.h"
BigInteger* construct(char data[], size_t length) {
if (length > 40)
return NULL;
BigInteger* bi = malloc(sizeof(BigInteger*));
bi->length = length;
bi->data = malloc(bi->length*sizeof(char));
intcpy(bi->data, data, bi->length);
return bi;
}
BigInteger* add(BigInteger* x, BigInteger* y) {
char* add_data(char*, char*, int*);
int len = (x->length > y->length) ? x->length : y->length;
char** resized = get_adjusted(x, y);
char* tmp_x = resized[0];
char* tmp_y = resized[1];
char* ret = add_data(tmp_x, tmp_y, &len);
if (ret == NULL)
return NULL;
BigInteger *b = construct(ret, len);
return b;
}
BigInteger* subtract(BigInteger* x, BigInteger* y) {
char** resized = get_adjusted(x, y);
char *tmp_x = resized[0];
char *tmp_y = resized[1];
enum Sign {
EQUAL = 0, POSITIVE = 1, NEGATIVE = 2
};
short ret_sign = EQUAL;
int i;
for (i = x->length - 1; i >= 0; i--) {
if (tmp_x[i] == tmp_y[i])
continue;
else if (tmp_x[i] > tmp_y[i]) {
ret_sign = POSITIVE;
break;
} else {
ret_sign = NEGATIVE;
break;
}
}
// TODO: separate the following logic into its own utility function
BigInteger* bi;
if (ret_sign == EQUAL) {
char ret[1] = {0};
bi= construct(ret, 1);
}else if (ret_sign == POSITIVE){
char ret[x->length];
for (i=0; i<x->length;i++){
int tmp = tmp_x[i]-tmp_y[i];
if (tmp <0){
tmp_x[i+1]--;
tmp = (tmp_x[i]+10)-tmp_y[i];
}
ret[i] = tmp;
}
bi=construct(ret, x->length);
}else{
char ret[y->length];
for (i=0; i<y->length;i++){
int tmp = tmp_y[i]-tmp_x[i];
if (tmp <0){
tmp_y[i+1]--;
tmp = (tmp_y[i]+10)-tmp_x[i];
}
ret[i] = tmp;
}
bi=construct(ret, y->length);
bi->sign = 1;
}
return bi;
}
char* get(BigInteger* bi) {
return bi->data;
}
void print(BigInteger* bi) {
char* d = bi->data;
if (bi->sign) printf("%c", '-');
int i;
for (i = (bi->length)-1; i>=0; --i) {
printf("%i", d[i]);
}
printf("\n");
}
char* add_data(char* x, char* y, int *len) {
int i, reminder = 0;
char *ret = malloc(sizeof(char) * *len);
for (i = 0; i < *len; i++) {
int tmp = x[i] + y[i] + reminder;
ret[i] = tmp % 10;
reminder = (tmp - ret[i]) / 10;
}
if (reminder) {
if (i==40){
fprintf(stderr, "Arithmetic OverFlown");
return NULL;
}else{
ret[i] =reminder;
(*len)++;
}
}
return ret;
}
static void intcpy(char* dest, char* src, int l) {
while (l-- > 0)
*dest++ = *src++;
}
static char** get_adjusted(BigInteger* x, BigInteger *y) {
char **ret = malloc(sizeof(char**));
int len = (x->length > y->length) ? x->length : y->length;
char *tmp_x = get(x);
char *tmp_y = get(y);
int diff;
if ((diff = len - x->length) > 0) {
intcpy(tmp_x, get(x), len);
while (diff > 0) {
tmp_x[x->length++] = 0;
diff--;
}
} else if ((diff = len - y->length) > 0) {
intcpy(tmp_y, get(y), len);
while (diff > 0) {
tmp_y[y->length++] = 0;
diff--;
}
}
ret[0] = tmp_x;
ret[1] = tmp_y;
return ret;
}
//main.c
#include <stdio.h>
#include "BigInteger.h"
void test_add1() {
printf("Start Testing ADD n");
char d1[] = { 1, 2}; // from right to left, so its value is 21
char d2[] = { 5}; // and this is 5
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = add(bi1, bi2);
print(ret);
printf("End Testing...n");
}
void test_add2() {
printf("Start Testing ADD n");
char d1[40];
char d2[40];
int i=0;
for (i=0; i<40;i++){
d1[i] = 3;
d2[i] = 5;
}
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = add(bi1, bi2);
print(ret);
printf("End Testing...n");
}
/**
* Will print "Arithmetic Overflow" and returns NULL
*/
void test_add3() {
printf("Start Testing ADD n");
char d1[40];
char d2[40];
int i=0;
for (i=0; i<40;i++){
d1[i] = 5;
d2[i] = 5;
}
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = add(bi1, bi2);
if (ret == NULL)
printf("NULLn");
//print(ret);
printf("End Testing...n");
}
void test_add4() {
printf("Start Testing ADD n");
char d1[] = { 9, 9};
char d2[] = { 9, 9};
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = add(bi1, bi2);
print(ret);
printf("End Testing...n");
}
void test_add5() {
printf("Start Testing ADD n");
char d1[] = { 1, 2, 0, 0, 1, 2, 3, 4, 5, 9 ,3, 1, 3, 4, 4, 2, 1}; // from right to left, so its value is 21
char d2[] = { 1, 3, 3, 4, 5, 5, 3, 0, 0, 0, 0, 0, 2, 1, 1, 1, 9}; // and this is 5
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = add(bi1, bi2);
print(ret);
printf("End Testing...n");
}
void test_subtract1() {
printf("Start Testing SUBTRACT n");
char d1[] = { 1, 2}; // this is 21
char d2[] = { 5, 2}; // and this is 25
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = subtract(bi1, bi2);
print(ret);
printf("End Testing...n");
}
void test_subtract2() {
printf("Start Testing SUBTRACT n");
char d1[] = { 9, 9};
char d2[] = { 9, 9};
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = subtract(bi1, bi2);
print(ret);
printf("End Testing...n");
}
void test_subtract3() {
printf("Start Testing SUBTRACT n");
char d1[40];
char d2[40];
int i=0;
for (i=0; i<40;i++){
d1[i] = 3;
d2[i] = 5;
}
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = subtract(bi1, bi2);
print(ret);
printf("End Testing...n");
}
void test_subtract4() {
printf("Start Testing SUBTRACT n");
char d1[] = { 1, 2, 0, 0, 1, 2, 3, 4, 5, 9 ,3, 1, 3, 4, 4, 2, 1}; // from right to left, so its value is 21
char d2[] = { 1, 3, 3, 4, 5, 5, 3, 0, 0, 0, 0, 0, 2, 1, 1, 1, 9}; // and this is 5
BigInteger* bi1 = construct(d1, sizeof(d1) / sizeof(char));
BigInteger* bi2 = construct(d2, sizeof(d2) / sizeof(char));
print(bi1);
print(bi2);
BigInteger *ret = subtract(bi1, bi2);
print(ret);
printf("End Testing...n");
}
int main(void) {
test_add1();
test_add2();
test_add3();
test_add4();
test_add5();
test_subtract1();
test_subtract2();
test_subtract3();
test_subtract4();
return 0;
}
How to compile the program:
1- copy the three above files to a new directory (say c_big_int)
ls -l
-rw-r--r-- 1 mhewedy mhewedy 4858 2011-04-05 22:41 main.c
-rw-r--r-- 1 mhewedy mhewedy 4440 2011-04-05 22:41 BigInteger.c
-rw-r--r-- 1 mhewedy mhewedy 712 2011-04-05 22:40 BigInteger.h
2- compile the BigInteger.c
cc -c BigInteger.c
3- make sure that the compilation process generated the object file:
ls -l
-rw-r--r-- 1 mhewedy mhewedy 3180 2011-04-05 22:48 BigInteger.o
-rw-r--r-- 1 mhewedy mhewedy 4858 2011-04-05 22:41 main.c
-rw-r--r-- 1 mhewedy mhewedy 4440 2011-04-05 22:41 BigInteger.c
-rw-r--r-- 1 mhewedy mhewedy 712 2011-04-05 22:40 BigInteger.h
4- Let's generate the binary file:cc -o main main.c -L. BigInteger.o
5- Now you can run the program using the following command:
./main
**EDIT** The code has been reformatted, if it is no longer working please let me know in the comments
2 comments:
Seems your comments in test cases are wrong, all comments are saying 21 and 5 :)
Yes... .)
Please Ignore comments in test cases
Post a Comment