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!