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
Seems your comments in test cases are wrong, all comments are saying 21 and 5 :)
ReplyDeleteYes... .)
ReplyDeletePlease Ignore comments in test cases