예제 #1
0
	bignum modulo(const bignum &bn1, const bignum &bn2)
	{
		bignum bn1_abs = bn1.absolute();
		bignum bn2_abs = bn2.absolute();
		bignum actual_quotient = bn1_abs / bn2_abs;

		if (bn1.isPositive() && bn2.isPositive())
		{
			bignum product_to_compare = actual_quotient.getRoundedDown(ONES_PLACE) * bn2;
			return bn1 - product_to_compare;
		}

		if (bn1.isPositive() && bn2.isNegative())
		{
			bignum product_to_compare = actual_quotient.getRoundedUp(ONES_PLACE) * bn2.absolute();
			return bn1 - product_to_compare;
		}

		if (bn1.isNegative() && bn2.isPositive())
		{
			bignum product_to_compare = actual_quotient.getRoundedUp(ONES_PLACE) * bn2;
			return bn1 + product_to_compare;
		}

		if (bn1.isNegative() && bn2.isNegative())
		{
			bignum product_to_compare = actual_quotient.getRoundedDown(ONES_PLACE) * bn2.absolute();
			return bn1 + product_to_compare;
		}

	}
예제 #2
0
	bignum greatestCommonFactor(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.isNegative() != bn2.isNegative())
			return greatestCommonFactor(bn1.absolute(), bn2.absolute());

		if (bn1.getDecimalCount() > 0 || bn2.getDecimalCount() > 0)
			throw error_handler(__FILE__, __LINE__, "Greatest common factor can only be found with two integers");

		if (bn1 == bn2)
			return bn1;

		bignum lowest = bn1 < bn2 ? bn1 : bn2;
		bignum highest = bn1 > bn2 ? bn1 : bn2;

		int converted_lowest = (int)lowest;
		int converted_highest = (int)highest;

		if (highest % lowest == 0)
			return lowest;

		for (int i = converted_lowest; i > 1; i--)
		{
			if (converted_lowest % i == 0 && converted_highest % i == 0)
			{
				bignum temp(i);
				temp.convertBase(bn1.getBase());
				return temp;
			}
		}

		bignum one(1);
		one.setBase(bn1.getBase());
		return one;
	}
예제 #3
0
	bignum lowestCommonMultiple(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.isNegative() != bn2.isNegative())
			return lowestCommonMultiple(bn1.absolute(), bn2.absolute());

		if (bn1.getDecimalCount() > 0 || bn2.getDecimalCount() > 0)
			throw error_handler(__FILE__, __LINE__, "Lowest common multiple can only be found with two integers");

		if (bn1 == bn2)
			return bn1;

		bignum lowest = bn1 < bn2 ? bn1 : bn2;
		bignum highest = bn1 > bn2 ? bn1 : bn2;

		if (highest % lowest == 0)
			return highest;

		for (int i = 1; lowest >= i; i++)
		{
			bignum product_check(highest * i);
			if (product_check % lowest == 0)
				return product_check;
		}

		throw error_handler(__FILE__, __LINE__, "An error has occurred");
	}
예제 #4
0
	bignum exponent(const bignum &base_value, const bignum &power, int precision)
	{
		if (base_value.getBase() != power.getBase())
			return exponent(base_value, power.getConverted(power.getBase()));

		bignum one(1);
		one.setBase(base_value.getBase());
		one.setPositive();

		if (power.isZero())
			return one;

		//if the power is negative, return 1/solution
		if (power.isNegative())
			return one / exponent(base_value, power.absolute());

		if (power.getDecimalCount() > 0)
		{
			if (power < 1)
			{
				bignum modified_power(power);
				modified_power.leftShift(power.getDecimalCount());
				bignum divisor(1);
				divisor.setBase(power.getBase());
				divisor.leftShift(power.getDecimalCount());

				bignum gcf(greatestCommonFactor(modified_power, divisor));
				modified_power /= gcf;
				divisor /= gcf;

				bignum divisor_root_of_base = jep::root(divisor, base_value, precision);
				return exponent(divisor_root_of_base, modified_power).getRoundedAllDigits(ONES_PLACE - precision);
			}

			else
			{
				bignum power_decimal = power % 1;
				bignum power_int = power.getRoundedDown(ONES_PLACE);

				return exponent(base_value, power_int, precision) * exponent(base_value, power_decimal, precision);
			}
		}

		bignum counter = power.absolute();
		bignum temp(base_value);

		//n^0 always returns 1
		if (power.isZero())
			return one;

		while (counter > one)
		{
			temp *= base_value;
			counter--;
		}

		return temp;
	}
예제 #5
0
	bool equals(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.getBase() != bn2.getBase())
			return equals(bn1, bn2.getConverted(bn1.getBase()));

		if (bn1.isNegative() != bn2.isNegative())
			return false;

		if (bn1.getDigitCount() != bn2.getDigitCount())
			return false;

		if (bn1.getDecimalCount() != bn2.getDecimalCount())
			return false;

		for (int i = bn1.getDigitCount(); i > 0; i--)
		{
			if (bn1.getDigit(i - 1) != bn2.getDigit(i - 1))
				return false;
		}
		return true;
	}
예제 #6
0
	bool greaterThan(const bignum &bn1, const bignum &bn2)
	{
		//if bases are different, convert the second and re-evaluate
		if (bn1.getBase() != bn2.getBase())
			return greaterThan(bn1, bn2.getConverted(bn1.getBase()));

		if (bn1 == bn2)
			return false;

		if (bn1.isNegative() && !bn2.isNegative())
			return false;

		if (!bn1.isNegative() && bn2.isNegative())
			return true;

		if (bn1.isNegative() && bn2.isNegative())
			return (lessThan(bn1.absolute(), bn2.absolute()));

		if (bn1.getDigitCount() > bn2.getDigitCount())
			return true;

		if (bn1.getDigitCount() < bn2.getDigitCount())
			return false;

		for (int i = bn1.getDigitCount() - 1; i >= 0; i--)
		{
			if (bn1.getDigit(i) > bn2.getDigit(i))
				return true;

			if (bn1.getDigit(i) < bn2.getDigit(i))
				return false;
		}

		return false;
	}
예제 #7
0
	bool lessThan(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.getBase() != bn2.getBase())
			return lessThan(bn1, bn2.getConverted(bn1.getBase()));

		if (bn1 == bn2)
			return false;

		if (bn1.isNegative() && !bn2.isNegative())
			return true;

		if (!bn1.isNegative() && bn2.isNegative())
			return false;

		if (bn1.isNegative() && bn2.isNegative())
			return (greaterThan(bn1.absolute(), bn2.absolute()));

		if (bn1.getDigitCount() < bn2.getDigitCount())
			return true;

		if (bn1.getDigitCount() > bn2.getDigitCount())
			return false;

		for (int i = bn1.getDigitCount() - 1; i >= 0; i--)
		{
			if (bn1.getDigit(i) < bn2.getDigit(i))
				return true;

			if (bn1.getDigit(i) > bn2.getDigit(i))
				return false;
		}

		return false;
	}
예제 #8
0
	bignum multiplyNumbers(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.getBase() != bn2.getBase())
			return multiplyNumbers(bn1, bn2.getConverted(bn1.getBase()));

		bignum temp(0);
		temp.setBase(bn1.getBase());

		if (bn1.isZero() || bn2.isZero())
			return temp;

		//multiply bn1 by each digit of bn2 independently, then add the values together
		int counter = bn2.getDigitRange();
		for (int i = 0; i < counter; i++)
		{
			int toMultiply = (ONES_PLACE - bn2.getDecimalCount()) + i;

			//verify function isn't checking beyond bounds of the stored array
			if (toMultiply >= 0)
			{
				if (toMultiply >= MAXDIGITS)
					throw error_handler(__FILE__, __LINE__, "The value being calculated is too large for the settings provided");

				bignum toAdd = multiplyNumbersSimple(bn1.absolute(), bn2.getDigit(toMultiply));

				toAdd.leftShift(i);
				temp += toAdd;
			}
		}

		if (bn1.isNegative() != bn2.isNegative())
			temp.setNegative();

		//adjust for added decimal places during multiplication
		temp.rightShift(bn2.getDecimalCount());

		temp.updateDigits();
		return temp;
	}
예제 #9
0
	bignum multiplyNumbersSimple(const bignum &bn1, int n)
	{
		if (n == 0)
		{
			bignum zero;
			zero.setBase(bn1.getBase());
			return zero;
		}

		bignum temp(bn1);

		//if both numbers are negative, make the result positive
		if (bn1.isNegative() == n < 0)
			temp.setPositive();

		//add the first number to itself n times
		for (int i = 0; i < (n - 1); i++)
			temp += bn1;

		temp.updateDigits();
		return temp;
	}
예제 #10
0
	bignum divideNumbers(const bignum &bn1, const bignum &bn2)
	{
		if (bn2.isZero())
			throw error_handler(__FILE__, __LINE__, "Cannot divide a number by zero");

		bignum temp;
		bool negative_result = (bn1.isNegative() != bn2.isNegative());

		if (bn1.getBase() != bn2.getBase())
			return divideNumbers(bn1, bn2.getConverted(bn1.getBase()));

		//set base of the return value to match that of the passed values
		int baseSet = bn1.getBase();
		temp.setBase(baseSet);

		bool remainder = false;
		bool end = false;
		int index = bn1.getDigitCount() - 1;

		//starting with the left-most digit, create a bignumber of that digit that matches the set base
		bignum number_to_compare(bn1.getDigit(index));
		number_to_compare.convertBase(baseSet);

		//ignore decimal places when comparing dividend to digits of the divisor
		bignum nextNumber = divideNumbersSimple(number_to_compare, bn2.absolute().noDecimal(), remainder);
		bignum number_to_subtract;
		number_to_subtract.setBase(baseSet);

		while (!end && index >= 0)
		{
			if (index >= MAXDIGITS)
				throw error_handler(__FILE__, __LINE__, "The value being calculated is too large for the settings provided");

			if (remainder == false && index < ONES_PLACE - bn1.getDecimalCount())
				end = true;

			temp.setDigit(index, nextNumber.getDigit(ONES_PLACE));
			index--;

			number_to_subtract = bn2.absolute().noDecimal() * nextNumber;
			number_to_subtract.updateDigits();
			number_to_compare -= number_to_subtract;
			number_to_compare.leftShift(1);

			if (index >= 0)
			{
				bignum digit(bn1.getDigit(index));
				digit.convertBaseSimple(number_to_compare.getBase());
				number_to_compare += digit;
			}

			nextNumber = divideNumbersSimple(number_to_compare, bn2.absolute().noDecimal(), remainder);

			if (index < 0)
				end = true;
		}

		if (negative_result && temp != 0)
			temp.setNegative();

		temp.leftShift(bn2.getDecimalCount());
		return temp;
	}
예제 #11
0
	bignum subtractNumbers(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.getBase() != bn2.getBase())
			return subtractNumbers(bn1, bn2.getConverted(bn1.getBase()));

		int base = bn1.getBase();
		bignum difference;
		difference.setBase(base);

		//evaluate the numbers being of equal absolute value
		if (bn1.absolute() == bn2.absolute())
		{
			//	-12 - 12 ---> -(12 + 12)
			if (bn1.isNegative() && !bn2.isNegative())
			{
				bignum temp = addNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}

			//	12 - -12 ---> 12 + 12
			if (!bn1.isNegative() && bn2.isNegative())
				return addNumbers(bn1.absolute(), bn2.absolute());

			//	-12 - -12 ---> 0
			if (bn1.isNegative() && bn2.isNegative())
			{
				bignum temp;
				temp.setBase(base);
				return temp;
			}
		}

		//evaluate the numbers if absolute first is larger than absolute second
		if (bn1.absolute() > bn2.absolute())
		{
			//	-12 - 8 ---> -(12 + 8)
			if (bn1.isNegative() && !bn2.isNegative())
			{
				bignum temp = addNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}

			//	12 - -8 ---> 12 + 8
			if (!bn1.isNegative()&& bn2.isNegative())
				return addNumbers(bn1.absolute(), bn2.absolute());

			//	-12 - -8 ---> -(12 - 8)
			if (bn1.isNegative() && bn2.isNegative())
			{
				bignum temp = subtractNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}
		}

		//evaluate the numbers if absolute first is smaller than absolute second
		if (bn1.absolute() < bn2.absolute())
		{
			//	8 - 12 ---> -(12 - 8)
			if (!bn1.isNegative()&& !bn2.isNegative())
			{
				bignum temp = subtractNumbers(bn2.absolute(), bn1.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}

			//	-8 - 12 ---> -(8 + 12)
			if (bn1.isNegative() && !bn2.isNegative())
			{
				bignum temp = addNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}

			//	8 - -12 ---> 8 + 12
			if (!bn1.isNegative() && bn2.isNegative())
				return addNumbers(bn1.absolute(), bn2.absolute());

			//	-8 - -12 ---> (12 - 8)
			if (bn1.isNegative() && bn2.isNegative())
				return subtractNumbers(bn2.absolute(), bn1.absolute());
		}

		int carry = 0;
		int digits = 0;
		int decimal = 0;
		//bool carry_negative = false;

		//sets decimal and digit values to the highest of each number
		decimal = (bn1.getDecimalCount() > bn2.getDecimalCount() ? bn1.getDecimalCount() : bn2.getDecimalCount());
		digits = (bn1.getDigitCount() > bn2.getDigitCount() ? bn1.getDigitCount() + 1 : bn2.getDigitCount() + 1);

		for (int i = (ONES_PLACE - decimal); i < digits + 1 && i >= 0; i++)
		{
			if (i >= MAXDIGITS)
				throw error_handler(__FILE__, __LINE__, "The value being calculated is too large for the settings provided");

			int tempNumber = bn1.getDigit(i) - bn2.getDigit(i);

			tempNumber -= carry;

			if (tempNumber < 0)
			{
				tempNumber += base;
				carry = 1;
			}

			else carry = 0;

			difference.setDigit(i, tempNumber);
		}

		difference.updateDigits();
		difference.setBase(base);
		return difference;
	}
예제 #12
0
	bignum addNumbers(const bignum &bn1, const bignum &bn2)
	{
		if (bn1.getBase() != bn2.getBase())
			return addNumbers(bn1, bn2.getConverted(bn1.getBase()));

		if (bn1.absolute() == bn2.absolute())
		{
			//	-12 + 12 or 12 + -12 ---> 0
			if (bn1.isNegative() != bn2.isNegative())
			{
				bignum temp;
				temp.setBase(bn1.getBase());
				return temp;
			}

			// -12 + -12 ---> -(12 + 12)
			if (bn1.isNegative() && bn2.isNegative())
			{
				bignum temp(addNumbers(bn1.absolute(), bn2.absolute()));
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}
		}

		if (bn1.absolute() > bn2.absolute())
		{
			//	-12 + 8 ---> -(12 - 8)
			if (bn1.isNegative() && !bn2.isNegative())
			{
				bignum temp = subtractNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}

			//	12 + -8 ---> 12 - 8
			if (!bn1.isNegative() && bn2.isNegative())
				return subtractNumbers(bn1.absolute(), bn2.absolute());

			//	-12 + -8 ---> -(12 + 8)
			if (bn1.isNegative()&& bn2.isNegative())
			{
				bignum temp = addNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}
		}

		if (bn1.absolute() < bn2.absolute())
		{
			//	-8 + 12 ---> 12 - 8
			if (bn1.isNegative() && !bn2.isNegative())
			{
				bignum temp = subtractNumbers(bn2.absolute(), bn1.absolute());
				temp.updateDigits();
				return temp;
			}

			//	8 + -12 ---> 8 - 12
			if (!bn1.isNegative() && bn2.isNegative())
				return subtractNumbers(bn1.absolute(), bn2.absolute());

			// -8 + -12 ---> -(8 + 12)
			if (bn1.isNegative() && bn2.isNegative())
			{
				bignum temp = addNumbers(bn1.absolute(), bn2.absolute());
				temp.setNegative();
				temp.updateDigits();
				return temp;
			}
		}

		int carry = 0;
		int digits = 0;
		int decimal = 0;

		//sets decimal and digit values to the highest of each number
		decimal = (bn1.getDecimalCount() > bn2.getDecimalCount() ? bn1.getDecimalCount() : bn2.getDecimalCount());
		digits = (bn1.getDigitCount() > bn2.getDigitCount() ? bn1.getDigitCount() + 1 : bn2.getDigitCount() + 1);

		bignum sum;
		int base = bn1.getBase();

		for (int i = (ONES_PLACE - decimal); i < digits + 1 ; i++)
		{
			if (i >= MAXDIGITS)
				throw error_handler(__FILE__, __LINE__, "The value being calculated is too large for the settings provided");

			int tempNumber = bn1.getDigit(i) + bn2.getDigit(i);

			tempNumber += carry;

			if (tempNumber>(base - 1))
			{
				tempNumber -= base;
				carry = 1;
			}

			else carry = 0;

			sum.setDigit(i, tempNumber);
		}

		sum.updateDigits();
		sum.setBase(base);
		return sum;
	}
예제 #13
0
	bignum root(const bignum &nth_root, const bignum &base_number, int decimal_places)
	{	
		//std::cout << "root calc" << std::endl;
		if (nth_root.getBase() != base_number.getBase())
			return root(nth_root, base_number.getConverted(nth_root.getBase()), decimal_places);

		//TODO: verify that the 2.5th root of -2 is irrational, 
		if (base_number.isNegative())
		{
			if (nth_root.getDecimalCount() > 0 || nth_root % 2 == 0)
				throw error_handler(__FILE__, __LINE__, "The program attempted to compute an irrational value");

			else return root(nth_root, base_number.absolute(), decimal_places) * -1;
		}	

		if (nth_root.isNegative())
		{
			bignum one(1);
			one.setBase(base_number.getBase());
			return root(nth_root.absolute(), one / base_number, decimal_places);
		}

		if (base_number == 0 || base_number == 1)
			return base_number;

		//cross-checks the root being tested to the precision threshold specified
		bignum precision_check(1);
		precision_check.setBase(nth_root.getBase());
		precision_check.rightShift(decimal_places);
		bignum range_low = base_number - precision_check;
		bignum range_high = base_number + precision_check;

		bignum root_test;
		root_test = base_number < 1 ? base_number * nth_root : base_number / nth_root;

		//TODO: refine increment function to scale depending on the size of the number being tested
		bignum increment(1);
		increment.setBase(nth_root.getBase());
		if (base_number < 1)
			increment.rightShift(1);

		bignum answer_check;
		answer_check.setBase(nth_root.getBase());

		//sets once function finds general region of the answer
		bool approximate = false;

		for (;;)
		{
			//adjusts number precision to check for nearest round roots
			//prevents function from returning 3.99999 instead of 4
			if (!approximate)
				root_test.roundToIndex(ONES_PLACE - increment.getDecimalCount());

			answer_check = exponent(root_test, nth_root);

			if (answer_check > range_low && answer_check < range_high)
				return root_test;

			if (answer_check > base_number)
			{
				if (approximate)
				{
					root_test -= increment;
					increment.rightShift(1);
					root_test += increment;
				}

				else root_test /= nth_root;
			}
				
			else if (answer_check < base_number)
			{
				if (!approximate)
					approximate = true;

				root_test += increment;
			}
		}
	}