예제 #1
0
파일: bignum.c 프로젝트: jeffcomtw/RPNCAL
void multiply_bignum(bignum *a, bignum *b, bignum *c)
{
	bignum aCopy = *a;
	bignum tmp;
	int i, j;
	int digit;

	// TODO: compare a and b for the optimized performance.
	if (compareBignum(a, b) < 0)
	{
		multiply_bignum(b, a, c);
		return;
	}

	initializeBignum(c);
	rightShift(&aCopy, b->numFractions);

	// Multiple by the fractional numbers.
	for (i = 0; i < b->numFractions; i++)
	{
		digit = b->integers[i];

		// Add {digit} times.
		for (j = 1; j <= digit; j++)
		{
			addBignum(c, &aCopy, &tmp);
			*c = tmp;
		}

		leftShift(&aCopy, 1);
	}

	// Multiple by the integer numbers.
	for (i = 0; i <= b->numIntegers; i++)
	{
		digit = b->integers[i];

		for(j = 1; j <= digit; j++)
		{
			addBignum(c, &aCopy, &tmp);
			*c = tmp;
		}

		leftShift(&aCopy, 1);
	}

	c->sign = (a->sign == b->sign) ? PLUS : MINUS;

	optimizeBignum(c);
}
예제 #2
0
	bignum::bignum(vector<int> n, int set_base, bool is_negative)
	{
		initializeBignum();
		base = set_base;

		int count = (ONES_PLACE - 1) + n.size();
		for (vector<int>::iterator i = n.begin(); i != n.end()  && count >= 0; i++)
		{
			if (count >= MAXDIGITS)
				throw error_handler(__FILE__, __LINE__, "The value being calculated is too large for the settings provided");

			if (*i >= base)
				throw error_handler(__FILE__, __LINE__, "One of the values passed is beyond the given base");

			digits[count] = (*i);
			count--;
		}

		updateDigits();
		negative = is_negative;
	}
예제 #3
0
파일: bignum.c 프로젝트: jeffcomtw/RPNCAL
void addBignum(bignum *a, bignum *b, bignum *c)
{
	int carry = 0;
	int i = 0;
	int maxNumFractions = getMax(a->numFractions, b->numFractions);
	int maxNumDecimals = getMax(a->numIntegers, b->numIntegers);
	int left, right;
	int result;

	// Determine if the two numbers are both positive. If not, call the substract function.
	if (a->sign != b->sign)
	{
		// Call substract.
		if (a->sign == MINUS)
		{
			a->sign = PLUS;
			subtractBignum(b, a, c);
			a->sign = MINUS;
		}
		else
		{
			b->sign = PLUS;
			subtractBignum(a, b, c);
			b->sign = MINUS;
		}

		return;
	}

	if (a->sign == MINUS)
	{
		a->sign = b->sign = PLUS;
		addBignum(a, b, c);
		a->sign = b->sign = MINUS;
		c->sign = MINUS;
		return;
	}

	initializeBignum(c);
	c->numFractions = maxNumFractions;
	c->numIntegers = maxNumDecimals;

	// Adding the fractions.
	for (i = maxNumFractions - 1; i >= 0; i--)
	{
		left = (i <= a->numFractions - 1) ? a->fractions[i] : 0;
		right = (i <= b->numFractions - 1) ? b->fractions[i] :  0;
		result = left + right + carry;

		if (result >= 10)
		{
			carry = 1;
			result -= 10;
		}
		else
		{
			carry = 0;
		}

		c->fractions[i] = result;
	}

	// Adding the integers.
	for (i = 0; i < maxNumDecimals; i++)
	{
		left = (i < a->numIntegers) ? a->integers[i] : 0;
		right = (i < b->numIntegers) ? b->integers[i] : 0;
		result = left + right + carry;

		if (result >= 10)
		{
			carry = 1;
			result -= 10;
		}
		else
		{
			carry = 0;
		}

		c->integers[i] = result;
	}

	if (carry != 0)
	{
		c->integers[c->numIntegers] = 1;
		c->numIntegers++;
	}

	optimizeBignum(c);
}
예제 #4
0
파일: bignum.c 프로젝트: jeffcomtw/RPNCAL
// Transfer the large number in the string to a big number.
// Return 0 if succeed, 1 if fail.
int stringToBignum(char* string, bignum *num) {
	int i;
	int	j=0;
	int k = 0;
	int len = 0;
	int hasFranction = 0;
	char c;
	int charInteger = 0;

	int decimalsIndex = 0;
	int fractionIndex = 0;

	int numChars, numIntegers, numFractions;
	analizeNumString(string, &numChars, &numIntegers, &numFractions);

	decimalsIndex = numIntegers - 1;
	initializeBignum(num);
	num->numIntegers = 0;

	for (i = 0, len = numChars; i <= len; i++) {
		c = string[i];

		if (isspace(c) || c == '\0')
		{
			break;
		}
		else if(isdigit(c))
		{
			charInteger = c - '0';

			if (hasFranction == 0)
			{
				num->integers[decimalsIndex] = charInteger;
				decimalsIndex--;
				num->numIntegers++;
			}
			else if (hasFranction == 1)
			{
				num->fractions[k] = charInteger;
				k++;
				num->numFractions++;
			}
		}
		else if(c == '-')
		{
			num->sign = MINUS;
		}
		else if(c == '.')
		{
			hasFranction = 1;
		}
		else
		{
			return EXIT_FAILURE;
		}
	}

	optimizeBignum(num);

	return EXIT_SUCCESS;
}
예제 #5
0
파일: bignum.c 프로젝트: jeffcomtw/RPNCAL
bignum getZeroBignum()
{
	bignum num;
	initializeBignum(&num);
	return num;
}
예제 #6
0
파일: bignum.c 프로젝트: jeffcomtw/RPNCAL
int divide_bignum(bignum *a, bignum *b, bignum *c)
{
	int aSign, bSign;				/* temporary signs */
	int i;							/* counters */
	int numShiftRequired;
	int answerIndex;
	bignum aCopy, bCopy, tempNum;
	int compareResult;
	int count = 0;
	int isExiting = 0;
	int isIntegersDone = 0;

	if (isBignumZero(b))
	{
		// Divided by zero.
		return 0;
	}

	initializeBignum(c);

	if (isBignumZero(a))
	{
		return 1;
	}

	c->sign = (a->sign == b->sign) ? PLUS : MINUS;

	aSign = a->sign;
	bSign = b->sign;
	a->sign = b->sign = PLUS;

	aCopy = *a;
	bCopy = *b;

	if (b->numIntegers == 1 && b->integers[0] == 0)
	{
		for (i = 0; i < MAX_NUM_DIGITS; i++)
		{
			if (b->fractions[i] != 0)
			{
				break;
			}
		}

		numShiftRequired = (a->numIntegers - b->numIntegers) + i + 1;
	}
	else
	{
		numShiftRequired = (a->numIntegers > b->numIntegers) ? a->numIntegers - b->numIntegers : 0;
	}

	c->numIntegers = numShiftRequired + 1;
	leftShift(&bCopy, numShiftRequired);
	answerIndex = numShiftRequired;

	// Fill up the integers.
	while (answerIndex >= 0)
	{
		while (1)
		{
			if (isBignumZero(&aCopy))
			{
				isExiting = 1;
				break;
			}

			compareResult = compareBignum(&aCopy, &bCopy);

			if (compareResult < 0)
			{
				if (--answerIndex < 0)
				{
					isIntegersDone = 1;
					break;
				}

				leftShift(&aCopy, 1);
				continue;
			}

			subtractBignum(&aCopy, &bCopy, &tempNum);
			aCopy = tempNum;
			c->integers[answerIndex]++;
		}

		if (isIntegersDone || isExiting)
		{
			break;
		}
	}

	if (!isExiting)
	{
		answerIndex = 0;		
		leftShift(&aCopy, 1);
		c->numFractions++;

		// Fill up the fractions.
		while (answerIndex < MAX_NUM_DIGITS - 1)
		{
			while (1)
			{
				if (isBignumZero(&aCopy))
				{
					isExiting = 1;
					break;
				}

				compareResult = compareBignum(&aCopy, &bCopy);

				if (compareResult < 0)
				{
					if (++answerIndex >= MAX_NUM_DIGITS - 1)
					{
						isExiting = 1;
						break;
					}

					leftShift(&aCopy, 1);
					c->numFractions++;

					continue;
				}

				subtractBignum(&aCopy, &bCopy, &tempNum);
				aCopy = tempNum;
				c->fractions[answerIndex]++;
			}

			if (isExiting)
			{
				break;
			}
		}
	}

	optimizeBignum(c);

	a->sign = aSign;
	b->sign = bSign;

	return 1;
}
예제 #7
0
	bignum::bignum(float f, int decimal_places)
	{
		initializeBignum();

		vector<int> exponent, mantissa;
		bool sign = false;

		//based on 32-bit system architecture
		static int float_bits = 32, mantissa_delim = 23, exponent_delim = 31, exponent_bias = 127;

		union float_converter
		{
			float f;
			unsigned int u;
		};

		float_converter converter;
		converter.f = f;

		unsigned int compare = 1;

		//iterate through bits of the stored value, push bit value to appropriate container
		for (int i = 0; i < float_bits; i++)
		{
			if (i < mantissa_delim)
				mantissa.push_back(converter.u & compare == compare);

			else if (i < exponent_delim)
				exponent.push_back(converter.u & compare == compare);

			else sign = (converter.u & compare == compare);

			converter.u = converter.u >> 1;
		}

		//reversed to compensate for endianess
		std::reverse(mantissa.begin(), mantissa.end());
		std::reverse(exponent.begin(), exponent.end());

		//create the mantissa as a binary bignum
		bignum big_mantissa(mantissa, 2, false);
		big_mantissa.rightShift(mantissa_delim);

		//create the exponent as a binary bignum, adjust based on exponent bias
		bignum big_exponent(exponent, 2, false);
		bignum big_exponent_bias(exponent_bias);
		big_exponent_bias.convertBase(2);
		big_exponent -= big_exponent_bias;
		
		//generates multiplier of the floating format based on mantissa and exponent
		bignum mantissa_multiplier(10);
		mantissa_multiplier.setBase(2);
		mantissa_multiplier = jep::exponent(mantissa_multiplier, big_exponent);
		mantissa_multiplier.convertBase(2);
		
		//increment, since system architecture does not incorporate the 1 by default
		big_mantissa += 1;

		bignum temp = big_mantissa * mantissa_multiplier;

		if (sign)
			temp.setNegative();

		temp.convertBase(10);
		*this = temp;
		roundToIndex(ONES_PLACE - decimal_places);
	}
예제 #8
0
	bignum::bignum(double d, int decimal_places)
	{
		initializeBignum();

		vector<int> exponent;
		vector<int> mantissa;
		bool sign = false;

		static int double_bits = 64, mantissa_delim = 52, exponent_delim = 63, exponent_bias = 1023;

		union double_converter
		{
			double d;
			unsigned long long int u;
		};

		double_converter converter;
		converter.d = d;

		unsigned int compare = 1;

		for (int i = 0; i < double_bits; i++)
		{
			if (i < mantissa_delim)
				mantissa.push_back(converter.u & compare == compare);

			else if (i < exponent_delim)
				exponent.push_back(converter.u & compare == compare);

			else sign = (converter.u & compare == compare);

			converter.u = converter.u >> 1;
		}

		std::reverse(mantissa.begin(), mantissa.end());
		std::reverse(exponent.begin(), exponent.end());

		bignum big_mantissa(mantissa, 2, false);
		big_mantissa.rightShift(mantissa_delim);

		bignum big_exponent(exponent, 2, false);
		bignum big_exponent_bias(exponent_bias);
		big_exponent_bias.convertBase(2);
		big_exponent -= big_exponent_bias;

		//generates multiplier of the floating format
		bignum mantissa_multiplier(10);
		mantissa_multiplier.setBase(2);
		mantissa_multiplier = jep::exponent(mantissa_multiplier, big_exponent);
		mantissa_multiplier.convertBase(2);
		big_mantissa += 1;

		bignum temp = big_mantissa * mantissa_multiplier;

		if (sign)
			temp.setNegative();

		temp.convertBase(10);

		*this = temp;

		roundToIndex(ONES_PLACE - decimal_places);
	}
예제 #9
0
	bignum::bignum(string s, int baseGiven)
	{
		initializeBignum();
		base = baseGiven;

		vector <int> numbersToAdd;
		int numbersAdded = 0;
		int decimalNumbers = 0;

		for (int i = 0; i < s.length(); i++)
		{
			bool decimal = false;

			switch (s[i])
			{
			case ',': break;

			case '.':
				if (decimal == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple decimal points");

				else decimal = true;
				break;

			case '-':
				if (negative == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple negative symbols");

				else negative = true;
				break;

			default:
				char zero = '0';
				char letter = 'A';

				if (s[i] >= zero && s[i] <= zero + 9)
				{
					int digitToAdd = s[i] - zero;
					if (digitToAdd >= base)
						throw error_handler(__FILE__, __LINE__, "constructor failed, digit exceeds base desired");

					if (decimal == true)
						decimalNumbers++;

					numbersAdded++;
					numbersToAdd.push_back(digitToAdd);
					break;
				}

				else if (s[i] >= letter && s[i] <= letter + 27)
				{
					int digitToAdd = s[i] - letter + 10;
					if (digitToAdd >= base)
						throw error_handler(__FILE__, __LINE__, "constructor failed, digit exceeds base desired");

					if (decimal == true)
						decimalNumbers++;

					numbersAdded++;
					numbersToAdd.push_back(digitToAdd);
					break;
				}

				else throw error_handler(__FILE__, __LINE__, "constructor failed, invalid character(s) included");
				break;
			}
		}

		if (decimalNumbers > ONES_PLACE)
			throw error_handler(__FILE__, __LINE__, "constructor failed, number has too many decimal places");

		int startingPoint = ONES_PLACE + (numbersAdded - decimalNumbers) - 1;
		for (int i = 0; i < numbersToAdd.size(); i++)
		{
			int digitToAdd = numbersToAdd.at(i);
			int locationToSet = startingPoint - i;
			digits[locationToSet] = digitToAdd;
		}

		updateDigits();
	}
예제 #10
0
	bignum::bignum(string s)
	{
		initializeBignum();

		vector <int> numbersToAdd;
		int numbersAdded = 0;
		int decimalNumbers = 0;
		bool decimal = false;
		int commaNumbers = 0;
		bool comma = false;

		for (int i = 0; i < s.length(); i++)
		{
			switch (s[i])
			{
			case ',':
				if (decimal == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, comma included after decimal point");

				else if (comma == true && commaNumbers != 3)
					throw error_handler(__FILE__, __LINE__, "constructor failed, improper use of commas");

				else if (comma == false && numbersAdded > 3)
					throw error_handler(__FILE__, __LINE__, "constructor failed, improper use of commas");

				else if (numbersAdded == 0)
					throw error_handler(__FILE__, __LINE__, "constructor failed, improper use of commas");

				comma = true;
				commaNumbers = 0;

				break;

			case '.':
				if (decimal == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple decimal points");

				else decimal = true;

				break;

			case '-':
				if (decimal == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, negative symbol included after a decimal point");

				if (numbersAdded > 0)
					throw error_handler(__FILE__, __LINE__, "constructor failed, negative symbol included after a number");

				if (comma == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, negative sign included after a comma");

				if (negative == true)
					throw error_handler(__FILE__, __LINE__, "constructor failed, number contains multiple negative symbols");

				else negative = true;

				break;

			default:
				char zero = '0';

				if (s[i] >= zero && s[i] <= zero + 9)
				{
					int digitToAdd = s[i] - zero;
					if (digitToAdd >= base)
						throw error_handler(__FILE__, __LINE__, "constructor failed, digit exceeds base desired");

					if (decimal == true)
						decimalNumbers++;

					if (comma == true)
						commaNumbers++;

					numbersAdded++;
					numbersToAdd.push_back(digitToAdd);
					break;
				}

				else throw error_handler(__FILE__, __LINE__, "constructor failed, invalid character(s) included");

				break;
			}
		}

		if (decimalNumbers > ONES_PLACE)
			throw error_handler(__FILE__, __LINE__, "constructor failed, number has too many decimal places");

		int startingPoint = ONES_PLACE + (numbersAdded - decimalNumbers) - 1;
		for (int i = 0; i < numbersToAdd.size(); i++)
		{
			int digitToAdd = numbersToAdd.at(i);
			int locationToSet = startingPoint - i;
			digits[locationToSet] = digitToAdd;
		}

		updateDigits();
	}