C language to achieve high precision except high precision

Posted by NathanLedet on Sun, 19 Dec 2021 05:07:13 +0100

Freshman and Xiaobai try high precision except high precision

introduction

The author is a freshman. In the process of doing questions, he came into contact with high-precision division. He wrote this blog to help clarify his ideas. I hope this blog can help more students who have just come into contact with C language. If there are mistakes in the text, please correct them.

1, What is high precision division

High precision division is to divide large integers that cannot be represented by ordinary data types.

2, Why do you need high-precision division

In C language, the commonly used data types are int, long, long, double, etc., but the size of these data types is limited. When the input data is too large, these data types cannot realize their functions, and forced use may cause errors. In this case, we need high-precision division to complete the operation.

3, Implementation of high precision Division

thinking

reference resources High precision multiplication First of all, we know that the computer is stupid. Second, we know that we can go back to primary school to find the answer, so the implementation idea of high-precision division is very clear. That is the way to simulate manual division, that is, we should achieve the purpose of high-precision operation through vertical division.

data type

Similar to high-precision multiplication, we choose strings to store large integers (what a nuisance!)

Review of vertical division

Here we only look at the division rule of integers

1) Starting from the high position of the divisor, first look at the number of divisor, and then try to divide the first few digits of the divisor. If it is smaller than the divisor, try to divide by one more digit;

2) Write quotient on the divisor;

3) The remaining number after each division must be smaller than the divisor.

Implementation steps

1. Input
2. Trial removal (specific size shift)
3. End
4. Output

preparation

void High_Precision_Division(char c_dividend[], char c_divisor[], char c_quotient[]) {
	int i;
	int i_dividend[Number_Size];//Divisor
	int i_divisor[Number_Size];//Divisor
	int i_quotient[Number_Size];//merchant
	char temp_answer[Number_Size];
	int start;
	int flag;
	int length_temp_answer;
	int length_divisor = strlen(c_divisor);
	int length_dividend = strlen(c_dividend);
	memset(c_quotient, 0, length_quotient);
	memset(i_dividend, 0, sizeof(i_dividend));
	memset(i_divisor, 0, sizeof(i_divisor));
	memset(i_quotient, 0, sizeof(i_quotient));
	memset(temp_answer, 0, sizeof(temp_answer));//Complete initialization
	if (Size_Comparison(c_dividend, length_dividend, c_divisor, length_divisor) < 0) {
		c_quotient[0] = '0';
		return;
	}
	start = 0;
}

Carry out trial removal

We know that the trial division process is actually the ratio of size. If it is not large enough, move one bit, and if it is large enough, calculate the quotient. For convenience, we introduce a ratio function here.

int Size_Comparison(char str_1[], int length_1, char str_2[], int length_2) {
	int i;
	if (length_1 < length_2) {
		return -1;
	}
	else if (length_1 > length_2) {
		return 1;
	}
	else {
		for (i = 0; i < length_1; i++) {
			if (str_1[i] < str_2[i]) {
				return -1;
			}
			else if (str_1[i] > str_2[i]) {
				return 1;
			}
		}
		return 0;
	}
}

This function passes in two char s * and two int s. If - 1 is returned, the first one is small, 1 is large, and 0 is equal.
Now, in order to calculate the quotient, we need to introduce the function of high-precision subtraction. How many times can I try to divide, and the quotient is how many.

	//start represents the starting position of the divisor trial division
	while (length_dividend - start >= length_divisor) {
		if (length_dividend - start == length_divisor && Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {
			break;
		}
		//If the remaining number is not enough, except (the length is equal and less than), exit the loop
		if (Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {
			//If the length is enough but the number of peers is not enough, borrow one bit back
			i_quotient[start + length_divisor]++;//Corresponding position quotient plus one
			High_Precision_Subtraction(&c_dividend[start], length_divisor + 1, c_divisor, length_divisor, temp_answer, 1, &flag);
			//Subtract divisor from corresponding position
			length_temp_answer = strlen(temp_answer);
			//temp_ The answer stores the difference
			memset(&c_dividend[start], 0, sizeof(char) * (length_divisor + 1));
			start = start + length_divisor + 1 - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			//This section completes copying. Of course, you can also use functions, which will be optimized later
			memset(temp_answer, 0, sizeof(temp_answer));
		}
		else {//Similarly to the previous paragraph, if the length is the same, you can continue, and make a difference directly
			i_quotient[start + length_divisor - 1]++;
			High_Precision_Subtraction(&c_dividend[start], length_divisor, c_divisor, length_divisor, temp_answer, 1, &flag);
			length_temp_answer = strlen(temp_answer);
			memset(&c_dividend[start], 0, sizeof(char) * length_divisor);
			start = start + length_divisor - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			memset(temp_answer, 0, sizeof(temp_answer));
		}
	}
	//Complete the process of division

Processor

First remove the extra 0, which is the leading zero here, and then convert it back to the string

	for (i = 0; i < length_dividend; i++) {
		if (i_quotient[i]) {
			start = i;
			break;
		}
	}
	length_quotient = length_dividend - start;
	for (i = start; i < length_dividend; i++) {
		c_quotient[i - start] = i_quotient[i] + '0';
	}
	//Processor and output

All codes

void High_Precision_Division(char c_dividend[], char c_divisor[], char c_quotient[], int length_quotient) {
	int i;
	int i_dividend[Number_Size];//Divisor
	int i_divisor[Number_Size];//Divisor
	int i_quotient[Number_Size];//merchant
	char temp_answer[Number_Size];
	int start;
	int flag;
	int length_temp_answer;
	int length_divisor = strlen(c_divisor);
	int length_dividend = strlen(c_dividend);
	memset(c_quotient, 0, length_quotient);
	memset(i_dividend, 0, sizeof(i_dividend));
	memset(i_divisor, 0, sizeof(i_divisor));
	memset(i_quotient, 0, sizeof(i_quotient));
	memset(temp_answer, 0, sizeof(temp_answer));//Complete initialization
	if (Size_Comparison(c_dividend, length_dividend, c_divisor, length_divisor) < 0) {
		c_quotient[0] = '0';
		return;
	}
	start = 0;
	while (length_dividend - start >= length_divisor) {
		if (length_dividend - start == length_divisor && Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {//If the remaining number is not enough, exit the loop
			break;
		}
		if (Size_Comparison(&c_dividend[start], length_divisor, c_divisor, length_divisor) < 0) {//If the length is enough but the number of peers is not enough, borrow one bit back
			i_quotient[start + length_divisor]++;//Corresponding position quotient plus one
			High_Precision_Subtraction(&c_dividend[start], length_divisor + 1, c_divisor, length_divisor, temp_answer, 1, &flag);
			length_temp_answer = strlen(temp_answer);
			memset(&c_dividend[start], 0, sizeof(char) * (length_divisor + 1));
			start = start + length_divisor + 1 - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			memset(temp_answer, 0, sizeof(temp_answer));
		}
		else {
			i_quotient[start + length_divisor - 1]++;
			High_Precision_Subtraction(&c_dividend[start], length_divisor, c_divisor, length_divisor, temp_answer, 1, &flag);
			length_temp_answer = strlen(temp_answer);
			memset(&c_dividend[start], 0, sizeof(char) * length_divisor);
			start = start + length_divisor - length_temp_answer;
			for (i = 0; i < length_temp_answer; i++) {
				c_dividend[i + start] = temp_answer[i];
			}
			memset(temp_answer, 0, sizeof(temp_answer));
		}
	}
	//Complete the process of division
	for (i = 0; i < length_dividend; i++) {
		if (i_quotient[i]) {
			start = i;
			break;
		}
	}
	length_quotient = length_dividend - start;
	for (i = start; i < length_dividend; i++) {
		c_quotient[i - start] = i_quotient[i] + '0';
	}
	//Processor and output
	return;
}

4, Conclusion

This function actually uses subtraction, so the time complexity is very high. It is very easy to time out when processing a small divisor and a large divisor. The divisor will be optimized later. Thank you very much for reading!

Topics: C