// 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); } }
// Initialize a bigint to zero bigint init_bigint(){ char* num = (char*)malloc(2*sizeof(char)); num[0] = '0'; num[1] = '\0'; return make_bigint(num); }
// Multiply a big int with 10^d. 'd' is positive. bigint shift_by_power_of_10(bigint big_num, int d){ char* newValue = (char*)malloc((big_num.length+d+1)*sizeof(char));//Terminating with NULL. Hence, the +1 in size. int i = 0; for(i = 0;i<big_num.length;i++){ newValue[i] = big_num.value[i]; } for(i = big_num.length; i<(big_num.length+d);i++){ newValue[i] = '0'; } newValue[i] = '\0';//Terminating the string with NULL return make_bigint(newValue); }
int main(int argc, char* argv[]) { int n,i; scanf("%d",&n); bigint num,temp; char str[2]="1"; num=make_bigint(str); //printf("%s %d %d\n",num.arr,strlen(num.arr),num.sign); //print_bigint(num); //printf("\n"); for(i=1;i<=n;i++){ temp=int_to_bigint(i); num=bigint_mul(num,temp); //num.arr[strlen(num.arr)]='\0'; //print_bigint(num); } //num.arr[strlen(num.arr)]='\0'; //printf("%d\n",strlen(num.arr)); //printf("%s\n",num.arr); print_bigint(num); return 0; }
value make_constant(constant c) { struct obj *cst; switch (c->vclass) { case cst_string: cst = (value)alloc_string_length(c->u.string.str, c->u.string.len); cst->flags |= OBJ_READONLY | OBJ_IMMUTABLE; return cst; case cst_list: return make_list(c->u.constants); case cst_array: return make_array(c->u.constants); case cst_int: return makeint(c->u.integer); case cst_float: return (value)alloc_mudlle_float(c->u.mudlle_float); case cst_bigint: return make_bigint(c->u.bigint_str); case cst_table: return make_table(c->u.constants); case cst_symbol: return make_symbol(c->u.constpair); default: abort(); } }
//Here, 'a' and 'b' are both positive. //'a' is greater than 'b' //Do simple subtraction using borrowing. //Just do a string subtraction. Pass the string to make_bigint. Return the result obtained from that. bigint borrow_subtraction(bigint a, bigint b){ char* result_str = (char*)malloc((a.length+1)*sizeof(char)); result_str[a.length] = '\0'; int i = a.length-1, j = b.length-1; while(i>=0 && j>=0){ if((a.value[i]-b.value[j])>=0){ result_str[i] = a.value[i] - b.value[j] + 48; } else{ result_str[i] = a.value[i] - b.value[j] + 10 + 48; //Get the borrow from the nearest non-zero number and make the in between numbers as 99.. int k = i-1; while(a.value[k]=='0'){ a.value[k] = '9'; k--; } a.value[k]-=1; } i--; j--; } //At this point, 'j' has exhausted. Just copy the rest of the digits to the result_str. while(i>=0){ result_str[i] = a.value[i]; i--; } return make_bigint(result_str); }
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; }
string multiply(string num1, string num2) { return to_string(make_bigint(num1) * make_bigint(num2)); }
//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; } }
// Parse a string to make it a Big Integer bigint make_bigint(char* str){ if(!valid(str)){ bigint flag_bigInt = make_bigint("-1");//'-1' is useful to indicate an invalid string for factorial flag_bigInt.length = -1;//A negative length is like a flag indicating an invalid string //So, flag_bigint flags invalid strings for both, main and factorial at the same time. return flag_bigInt; } //Assume that a valid string has been entered at this point bigint number; if(str[0]=='-') number.pos = 0; else number.pos = 1;//The first digit can be '+' also. Take care of that. //Find the length of the string first. Allocate the memory to the new string. Then fill the string. int length = 0;//Stores the meaningful length without the trailing zeros int trailingZeros = 0;//counts the number of trailing zeros char* tempStr = str; if(number.pos==0) tempStr++;//Start the string from the digits after skipping the negative sign '-' int flag = 0;//This flag is used to check the trailing zeros in the beginning of a number //Find length while(*tempStr!='\0'){ if(flag==0 && *tempStr=='0') trailingZeros++; else if(*tempStr!='0' && flag==0){ flag = 1; length++; } else length++; tempStr++; } if(length==0)//all were zeros { number.length = 1; number.value = (char*)malloc(2*sizeof(char)); number.value[0] = '0'; number.value[1] = '\0'; return number; } //If the number was not zero, come here number.length = length; //Allocate memory dynamically number.value = (char*)malloc((length+1)*sizeof(char));//+1 for an extra null character at the end tempStr = str; if(number.pos==0) tempStr++;//Start the string from the digits after skipping the negative sign '-' int index=0; //Fill in the string for value while(index<length){ number.value[index] = tempStr[index+trailingZeros]; index++; } number.value[index] = '\0'; return number; }
// Adds two bigints and returns the result which is a bigint bigint bigint_add(bigint a, bigint b){ //If they are of the opposite signs, then send them for subtraction if(a.pos==0&&b.pos==1||a.pos==1&&b.pos==0){ if(a.pos==0){ a.pos = 1;//Make it positive and send it for subtraction. return bigint_sub(b,a);//Returns (b-a) } else{ b.pos = 1;//Make it positive and send it for subtraction. return bigint_sub(a,b);//Returns (a-b) } } //If of the same sign, then add. else{ bigint bigger_num, smaller_num;// Here the bigger number is in terms of the absolute quantity. if(!a.pos){ if(compare_bigint(a,b)==1){ bigger_num = b; smaller_num = a; } else if(compare_bigint(a,b)==-1){ bigger_num = a; smaller_num = b; } else{ //Both are equal. Assign any number to any variable. bigger_num = a; smaller_num = b; } } else{ if(compare_bigint(a,b)==1){ bigger_num = a; smaller_num = b; } else if(compare_bigint(a,b)==-1){ bigger_num = b; smaller_num = a; } else{ //Both are equal. Assign any number to any variable. bigger_num = b; smaller_num = a; } } //At this point, bigger_num has the larger number in absolute terms. The 'smaller_num' contains the other. //Now, create a new character array which can hold the sum of the two terms and pass that array to make_bigint //For the new character array, assign memory 1 greater than the length of the bigger_num. //In case the left hand most field doesn't get filled up, then assign 0 to it. make_bigint takes care of that. int new_length = bigger_num.length+1;//This length excludes the negative sign. char* new_value; if(bigger_num.pos==0){ new_value = (char*)malloc((new_length+1+1)*sizeof(char));//+1 for the negative sign and +1 for terminating it with NULL new_value[0] = '-'; new_value[new_length+1] = '\0';//Terminating with a null character } else{ new_value = (char*)malloc((new_length+1)*sizeof(char));//+1 for terminating it with null. new_value[new_length] = '\0';//Terminating with a null character } addValues(bigger_num, smaller_num, new_value, new_length);//Does string addition and stores the result in new_value return make_bigint(new_value); }//Else ends }