Exemplo n.º 1
0
int busque_bin_adic(bigint *I1, bigint *I2, bigint *adic, bigint *mult) {
  unsigned long long dmin = 1, dmax = BASE, d;
  int shift, cmp;
  libere_bigint(adic); libere_bigint(mult);
  while (dmin + 1 < dmax) {
    d = dmin + (dmax - dmin) / 2;
    if (!multiplique_bigint_por_escalar(I2, d, mult)) return 0;
    shift = I1->tam > mult->tam ? I1->tam - mult->tam : 0;
    if (!desloque_bigint_para_a_esquerda(mult, shift)) return 0;
    if ((cmp = compare_bigint(mult, I1)) > 0) dmax = d;
    else if (cmp == 0) break;
    else dmin = d;
  }
  d = dmin + 1;
  if (!multiplique_bigint_por_escalar(I2, d, mult)) return 0;
  shift = I1->tam > mult->tam ? I1->tam - mult->tam : 0;
  if (!desloque_bigint_para_a_esquerda(mult, shift)) return 0;
  if ((cmp = compare_bigint(mult, I1)) > 0) {
    d = dmin;
    if (!multiplique_bigint_por_escalar(I2, d, mult)) return 0;
    shift = I1->tam > mult->tam ? I1->tam - mult->tam : 0;
    if (!desloque_bigint_para_a_esquerda(mult, shift)) return 0;
  }
  if (!leia_bigint_da_string(adic, "0")) return 0;
  adic->V[0] = d;
  if (!desloque_bigint_para_a_esquerda(adic, shift)) return 0;
  return 1;
}
Exemplo n.º 2
0
int divida_bigint(bigint *I1, bigint *I2, bigint *I3, bigint *I4) {
  bigint I2abs, quoc, mod, adic, mult;
  inicialize_bigint(&I2abs); inicialize_bigint(&quoc);
  inicialize_bigint(&mod); inicialize_bigint(&adic);
  inicialize_bigint(&mult);
  if (ZERO(*I2)) ABORTE_DIVISAO(&I2abs, &quoc, &mod, &adic, &mult);
  if (!abs_bigint(I1, &mod) || !abs_bigint(I2, &I2abs) ||
      !leia_bigint_da_string(&quoc, "0"))
    ABORTE_DIVISAO(&I2abs, &quoc, &mod, &adic, &mult);
  while (compare_bigint(&I2abs, &mod) <= 0) {
    if (!busque_bin_adic(&mod, &I2abs, &adic, &mult))
      ABORTE_DIVISAO(&I2abs, &quoc, &mod, &adic, &mult);
    if (!subtraia_bigint(&mod, &mult, &mod) ||
        !some_bigint(&quoc, &adic, &quoc))
      ABORTE_DIVISAO(&I2abs, &quoc, &mod, &adic, &mult);
  }
  if (I1->sinal && !(I2->sinal))
    quoc.sinal = 0;
  else if (!(I1->sinal)) {
    if (!leia_bigint_da_string(&adic, "1") ||
        !some_bigint(&quoc, &adic, &quoc) ||
        !subtraia_bigint(&I2abs, &mod, &mod))
      ABORTE_DIVISAO(&I2abs, &quoc, &mod, &adic, &mult);
    if (I2->sinal) quoc.sinal = 0;
  }
  libere_bigint(I3);
  I3->sinal = quoc.sinal; I3->tam = quoc.tam; I3->V = quoc.V;
  libere_bigint(I4);
  I4->sinal = mod.sinal; I4->tam = mod.tam; I4->V = mod.V;
  FINALIZE_DIVISAO(&I2abs, &adic, &mult);
}
Exemplo n.º 3
0
// 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();
		}

	}
}
Exemplo n.º 4
0
// 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;
}
Exemplo n.º 5
0
//Uses subtraction repeatedly to find the remainder and the quotient.
//Stores the remainder in a new bigint and uses 'pos' to store the quotient.
//returns this new bigint
bigint get_remainder_quotient(bigint dividend, bigint divisor){

	int quotient = 0;

	while(compare_bigint(dividend, divisor)>=0){
		dividend = bigint_sub(dividend,divisor);
		quotient+=1;
	}

	dividend.pos = quotient;//Will be 1 anyway, but to ensure it. Not very crucial.
	return dividend;
}
Exemplo n.º 6
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;
	}
}
Exemplo n.º 7
0
// 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
}