int main(void) { bigint_t a = init_bigint(123, 10); bigint_t b = init_bigint(111, 10); print_bigint(a); printf("\n"); print_bigint(b); printf("\n"); bigint_t r = add(a,b); print_bigint(r); printf("\n"); return 0; }
// Converts an integer to a bigint bigint int_to_bigint(int num){ if(num==0) return init_bigint(); else{ int length = 0; int tempNum = num; while(tempNum!=0){ tempNum/=10; length++; } if(num<0) length++; char* value = (char*)malloc((length+1)*sizeof(char)); value[length] = '\0';//Terminate the string with a NULL character if(num<0) value[0] = '-'; int i = length-1; tempNum = num>0 ? num:-num; while(tempNum!=0){ value[i] = (tempNum%10)+48; tempNum/=10; i--; } return make_bigint(value); } }
// Subtracts two bigints and returns the result which is a bigint // Returns a-b bigint bigint_sub(bigint a, bigint b){ if(a.pos==0&&b.pos==1){ b.pos = 0; return bigint_add(a,b); } else if(a.pos==1&&b.pos==0){ b.pos = 1; return bigint_add(a,b); } //At this point, both the numbers are of the same sign. So, a normal subtraction will work. else{ int max_num = compare_bigint(a,b); //Case: a>b and both are negative. Example: a = -20 ; b = -30 //a-b = (-x) - (-y) = y-x. 'y' and 'x' are positive. And 'y' is greater than 'x'. if(a.pos==0 && max_num==1){ b.pos = 1; a.pos = 1; return bigint_sub(b,a);//Returns (y-x). 'y' and 'x' are positive. } //Case: b>a and both are negative //a-b = (-x) - (-y) = y-x. 'y' and 'x' are positive. 'x' is greater than 'y'. //So, do x-y and then change the sign to negative. Then return. else if(a.pos==0 && max_num==-1){ a.pos = 1; b.pos = 1; bigint tempNo = bigint_sub(a,b); tempNo.pos = 0; return tempNo; } // Case: b>a and both are positive // a-b = x-y. 'x' and 'y' are positive // Do y-x and change the sign, then return. else if(a.pos==1 && max_num==-1){ bigint tempNo = bigint_sub(b,a); tempNo.pos = 0; return tempNo; } //Case: a>b and both are positive else if(a.pos==1 && max_num==1){ return borrow_subtraction(a,b); } //Case: Both are equal. Return 0. else{ return init_bigint(); } } }
// Multiplies two big ints and returns a bigint bigint bigint_mul(bigint a, bigint b){ // Idea: Multiply the bigger number by a digit of the smaller number. Then shift by the digit's 10's place. Add this newly found // multiplication to the already calculated result. Keep adding until all the digits of the smaller number exhaust. bigint multiplicand_table[9];// [0] stores the multiplicand. [1] stores multiplicand*2. [2] stores multiplicand*3 and so on. int positive = 0;//Stores whether the multiplication is positive or negative. 0 means negative. 1 means positive. if((a.pos==0 && b.pos==0)||(a.pos==1 && b.pos==1)) positive = 1; else positive = 0; a.pos = 1; b.pos = 1;//Make both the numbers positive for multiplication. int compare = compare_bigint(a,b); bigint bigger_num, smaller_num; //If 'a' is greater than or equal to 'b' then do this. if(compare==1||compare==0){ bigger_num = a; smaller_num = b; } //If 'b' is greater than 'a' then do this. else{ bigger_num = b; smaller_num = a; } //Now fill the multiplicand table from 1 to 9. multiplicand_table[0] = bigger_num;// bigger_num*1 multiplicand_table[1] = bigint_add(bigger_num,bigger_num);// bigger_num*2 multiplicand_table[2] = bigint_add(multiplicand_table[1],multiplicand_table[0]);//bigger_num*3 multiplicand_table[3] = bigint_add(multiplicand_table[2], multiplicand_table[0]);//bigger_num*4 multiplicand_table[4] = bigint_add(multiplicand_table[3], multiplicand_table[0]);//bigger_num*5 multiplicand_table[5] = bigint_add(multiplicand_table[4], multiplicand_table[0]);//bigger_num*6 multiplicand_table[6] = bigint_add(multiplicand_table[5], multiplicand_table[0]);//bigger_num*7 multiplicand_table[7] = bigint_add(multiplicand_table[6], multiplicand_table[0]);//bigger_num*8 multiplicand_table[8] = bigint_add(multiplicand_table[7], multiplicand_table[0]);//bigger_num*9 bigint result = init_bigint(); int i = 0;//iterator for(i = smaller_num.length-1;i>=0;i--){ if((smaller_num.value[i]-48)>=1){//Only if the digit is non zero will it add to the result. bigint tempNum = shift_by_power_of_10(multiplicand_table[smaller_num.value[i]-48-1],(smaller_num.length-1-i)); result = bigint_add(result, tempNum); } } result.pos = positive; return result; }
int main( int argc, char* argv[] ) { char cmd[ BUF_SIZE ]; // NOTE: Uncomment this once you've implemented this function bigint result = init_bigint(); //bigint result; // At the end of every arithmetic operation update the result. // In an infinite loop, get input from user while( 1 ) { char* op = NULL; // Store the operation // Get a line of input from the user fgets( cmd, BUF_SIZE, stdin ); // Parse the line using strtok // Note: Given a string like "a b c d", strtok returns "a" the first // time it's called, and "b", "c", "d" and NULL subsequently, if the // first argument is NULL. Read the manpage for more details op = strtok( cmd, " " ); // If the last line is a new line, make it a null character int len = strlen( op ); if( op[ len-1 ] == '\n' ) op[ len-1 ] = 0; // Match the operation, and do appropriate action if( strcmp( op, "quit" ) == 0 || op[0] == EOF ) { // Quit when you see this break; } else if( strcmp( op, "set" ) == 0 ) { // set <data> // Sets a big int value to data int data; if( read_args1( &data ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting // printf( "Setting value as %d\n", data ); // NOTE: Uncomment this once you've implemented this function result = int_to_bigint(data); } } else if( strcmp( op, "add" ) == 0 ) { // add <num1> <num2> // Adds two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Add %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_add( a, b); print_bigint(result); } } else if( strcmp( op, "sub" ) == 0 ) { // sub <num1> <num2> // Subtracts two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Subtract %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_sub( a, b); print_bigint(result); printf("\n"); } } else if( strcmp( op, "mul" ) == 0 ) { // mul <num1> <num2> // Multiplies two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Multiply %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_mul( a, b); print_bigint(result); } } else if( strcmp( op, "div" ) == 0 ) { // add <num1> <num2> // Adds two bigints and then prints the result char num1[512]; char num2[512]; if( read_args2( num1, num2 ) ) { // NOTE: This printf line has been added to help debug. Should be // removed before submitting //printf( "Divide %s and %s\n", num1, num2 ); // NOTE: Uncomment this once you've implemented this function bigint a = make_bigint(num1); bigint b = make_bigint(num2); result = bigint_div( a, b); print_bigint(result); } } else { printf( "Invalid command\n" ); } } return 0; }
//TODO: Define the division for negative numbers. Define it simply as the truncation of the fractional part. // Divides two bigints and returns a bigint similar to 9/4 = 2 // Long division method. bigint bigint_div(bigint a, bigint b){ if(compare_bigint(b, make_bigint("0"))==0){ printf("Divide by ZERO error.\n"); return make_bigint("0"); } //Take care of the sign first int positivity = ((a.pos==1&&b.pos==1)||(a.pos==0&&b.pos==0))?1:0; a.pos = 1; b.pos = 1; //Now check if we really need to divide in the first place. int max_flag = compare_bigint(a,b); if(max_flag<0) return init_bigint();//No need to divide as the dividend is lesser in magnitude than the divisor. else if(max_flag==0){ bigint tempBigInt = make_bigint("1"); tempBigInt.pos = positivity; return tempBigInt; } else{ char toAppend[2]; toAppend[1] = '\0'; //Quotient stores the final answer we need to return. For every character seen in the dividend, a number //gets added to the quotient. char* quotient = (char*)malloc((a.length+1)*sizeof(char)); quotient[0] = '\0'; //The current dividend can be at most the divisor's length +1. The extra +1 is for '\0'. char* current_dividend_str = (char*)malloc((b.length+1+1)*sizeof(char)); current_dividend_str[0] = '\0'; //Long division int dividend_index = 0;//This stores the current dividend index and acts as the iterator in the long division method //Take character by character from the dividend and perform long division while(dividend_index<a.length){ toAppend[0] = a.value[dividend_index]; strcat(current_dividend_str, toAppend); bigint current_dividend_bigint = make_bigint(current_dividend_str); int compare_division_state = compare_bigint(current_dividend_bigint, b); if(compare_division_state==-1){ quotient[dividend_index] = '0'; } else{ //remainder is indeed positive. So the 'pos' field is redundant. So, we use the 'pos' field to store the quotient. //The value field stores the remainder. Length stores the length of the remainder. //The quotient will only be a single digit. bigint remainder = get_remainder_quotient(current_dividend_bigint, b); quotient[dividend_index] = remainder.pos+48;// 'pos' stores the remainder. 48 is the ASCII value of 0. strcpy(current_dividend_str,remainder.value); } dividend_index++; } bigint tempBigInt = make_bigint(quotient); tempBigInt.pos = positivity; return tempBigInt; } }