[High-precision algorithm]|Basic algorithm|Addition, subtraction, multiplication and division under high precision, board algorithm. |Integer high-precision algorithm|Detailed code

First, what problem does high precision solve?

The so-called high-precision algorithms actually solve simple addition, subtraction, multiplication, and division operations, but why do we call them a class of algorithms? Isn't there related operators in C language that can perform operations? This requires us to know that operations in C language are certainly possible, but there are certain restrictions. We know that when performing operations, we need to use related variables to store data for operations. long The long variable is the largest integer variable, and the maximum value it can reach is only 10 18 . If we want to perform calculations with larger values, we cannot handle them, so we propose a high-precision algorithm.

High precision refers to not only downward (decimal point to the right) precision, but also upward (decimal point to the left) precision

Second, high-precision algorithm

1. The idea of ​​high precision algorithm

The algorithm idea of ​​high-precision addition, subtraction, multiplication and division is actually the same. We cannot process data, so we have to think about how people process data. Taking high-precision addition as an example, when we add, we use step-by-step We can start from this direction to solve the problem by means of carry. For handwritten addition, we must first find a breakthrough and then process the entire data. The core idea of ​​the high-precision algorithm is to reduce the number to 1 : divide a very long value into one value, and perform operations on one value, so that our problem is very simplified, that is, one is the characteristic operation of each algorithm, such as addition, subtraction, multiplication, and division. The other is a general solution on how to separate these high-precision data.

2, Storage of high-precision data

There are many storage methods for high-precision data, but in order to simplify the operation, we finally chose the vector array storage method. First, when we read in high-precision data, we need to use the string data type to read in, and then we put some data one by one When one is read into the vector , it is necessary to ensure that the push vector is pushed from the low bit to the high bit, because only in this way can the corresponding relationship of the values ​​be guaranteed, and it is convenient to carry.
insert image description here

The whole operation is relatively simple, but it should be noted that the data in the str of this operation needs some processing before being pushed in, because the numbers in str are of character type. What we need to push in is a number to perform calculations, so we need to perform a simple str[i] - '0' , and then proceed after completing this operation.

Supplementary vector basic operations
Definition: vector <data type> variable name;
call: (subscript) Start from 0, to n - 1
size: B.size() Return size
Push: C.push_back()

Complete data push-in

#include <iostream>
#include <string>
#include <vector>

using namespace std ;
int main ()
{
    
    
	string a;
	vector <int> A;
	cin >> a; 
	for(int i = a.length() - 1 ; i >= 0 ; i -- )
		A.push_back(a[i] - '0');
		//存储:1.反存储 , 2.减去'0' 

	for(int i = 0 ; i < A.size() ; i ++ )
		cout << A[i] ;
	puts("") ;
	return 0 ;
}

Three, high-precision addition

1. Algorithm ideas

First of all, we know that we have stored the data in low order . How do we break down this large operation into small operations to solve it? We have to find a solution from the original idea of ​​addition. We can run the i-th operation each time according to the carry method, and add the carry of the previous bit, and then we store it in a new array. When both sides are When it is empty, we end this algorithm. When the carry is 1, we carry one bit for the target array , and finally we return the array to complete this operation.

Of course, the output of the array should also be reversed.

2, algorithm code

#include <iostream>
#include <vector>
#include <string>

using namespace std ;

vector <int> add(vector<int> &A ,vector<int> &B)
//f1.&取地址运算能加快速度 , 能加上的时候尽量加上.
{
    
    
	int t = 0 ;
	//存数的指针
	vector <int> C;
	for(size_t i = 0 ; i < A.size() || i < B.size() ; i ++ )
	{
    
    
		if(i < A.size()) t += A[i] ;
		if(i < B.size()) t += B[i] ;
		C.push_back(t % 10);
		t /= 10;
	}
	if(t)  C.push_back(1) ;
	return C ;
}

Four, high-precision subtraction

1. Algorithm ideas

After learning about high-precision addition, we realized that this algorithm is actually controlled by something like a pointer. We rely on this pointer to assign a value to our target array every time . The key to solving high-precision problems is actually processing The problem with this pointer. We have to think about this subtraction operation. In the subtraction operation, we know that there are two operations: big-small and small-big . How to complete these two operations, we can turn these two into one. Let’s first judge which one is which The two cases are then combined into one of the cases for processing. We can implement the operation of converting A - B. First, let's judge which number is large.

bool cmp (vector<int> &A , vector<int> &B)
{
    
    
    if(A.size() != B.size()) return A.size() > B.size();

    for(int i = A.size() -  1 ; i >= 0 ;i --)
        if(A[i] != B[i])
            return A[i] > B[i];
        return true ;

}

After completing this operation, we can set a judgment branch structure on the main function to satisfy A > B. Then we have to complete the main operation of the subtraction

vector <int> sub(vector <int> &A ,vector<int> &B)
{
    
    
    int t =  0 ;
    //指针为 t ,t代表当前A - B 的值
    vector <int> C;
    for(size_t i = 0 ; i < A.size() ; i ++ )
    {
    
    
        t += A[i] ;
        //完成 + A
        if(i < B.size() ) t -=B[i] ;
        //完成 - B
        C.push_back((t + 10) % 10 );
        if(t >= 0)  t =  0 ;
        else t  =  -1 ;
        //完成为下一位的赋值
    }
    while (C.size() > 1 && C.back() == 0)   C.pop_back() ;
    return C ;
}

Next, let's look at the overall code

#include <iostream>
#include <vector>

using namespace std;

bool cmp (vector<int> &A ,vector<int> &B )
{
    
    
    if(A.size() != B.size() )   return A.size() > B.size() ;
    for(int  i = A.size() - 1; i >=0 ; i -- )
        if(A[i] != B[i])
            return A[i] > B[i] ;
        return true ;
}

vector <int> sub(vector <int> &A , vector <int> &B)
{
    
    
    vector <int> C;
    for(int i = 0 , t = 0;i <= A.size() - 1; i ++ )
    {
    
    
        t = A[i] - t ;
        if(i < B.size() )  t -= B[i];
        C.push_back( ( t + 10 ) % 10 );
        if(t<0) t=1;
        else  t=0;
    }
    while (C.size ()>1 && C.back()==0)  C.pop_back();
    return C;
}

int main ()
{
    
    
    string a , b ;
    vector <int> A ,B ,C ;
    cin >> a >> b ;
    for(int i = a.length() - 1; i >= 0 ; i --)
        A.push_back(a[i] - '0');
    for(int i = b.length() - 1 ; i >= 0 ; i --)
        B.push_back(b[i] - '0');
    if(cmp(A,B))
    {
    
    
        auto C=sub(A,B);
        for(int i=C.size()-1;i>=0;i--) cout << C[i];
    }
    else 
    {
    
    
        auto C=sub(B,A);
       cout<<"-";
        for(int i=C.size()-1;i>=0;i--)  cout<<C[i];
    }
    return 0;
}

Five, high-precision multiplication

1. Algorithm ideas

Compared with the first two, high-precision multiplication can be said to be simpler. It roughly continues the algorithm idea of ​​high-precision addition. This high-precision multiplication cannot be regarded as a complete high-precision multiplication. This is a high-precision * An algorithm with low precision . This algorithm involves an algorithm to delete leading zeros and an algorithm similar to a pointer we mentioned earlier. This pointer stores the value of each multiplication and outputs the end of each time.

2, code

#include <iostream>
#include <vector>

using namespace std ;

vector<int> mul (vector<int> & A ,int b)
{
    
    
    int t = 0 ;
    //相当于整个题目的指针
    vector <int> B ;
    for(int i = 0 ; i < A.size() || t ; i ++)
    {
    
    
        if(i < A.size()) t += A[i] * b ;
        B.push_back(t % 10);
        t /= 10 ;
    }
    while (B.size() > 1 && B.back() == 0)   B.pop_back();
    return B ;
}

int main ()
{
    
    
    int a ;
    string b ;
    
    vector <int> A , B;
    cin >> b >> a ;

    for(int i = b.length() - 1 ; i >= 0 ; i -- )
        A.push_back(b[i] - '0');
    B = mul(A,a);
    for(int i = B.size() - 1 ;i >= 0 ; i --)
        cout << B[i] ;

    return 0 ;
}

Six, high-precision division

1. Algorithm ideas

First of all, this algorithm is different from the previous algorithms. Although this algorithm is inverse data storage, it still performs operations from high bits at the end. The whole algorithm has been reversed twice, besides, his pointer and his pointer point to his remainder, each stage points to the remainder of each stage, the idea is similar to multiplication

Supplementary knowledge: In order to remove leading zeros, we need to use
the reverse function in the algorithm header file (using iterators)

2. Code

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std ;

vector <int> div(vector <int> &B ,int a ,int &r)
{
    
    
    r = 0 ;
    vector <int> C ;
    for(int i = B.size() - 1 ; i >= 0 ; i -- )
    {
    
    
        r = r * 10 + B[i] ;
        C.push_back(r / a);
        r %= a ;
    }
    reverse(C.begin(),C.end());
    while (C.back() == 0 && C.size() > 1 ) C.pop_back();
    return C ;
}

int main ()
{
    
    
    int  a , r;
    string b ;
    cin >> b >> a ;
    vector <int> B , C;
    for(int i = b.size() - 1 ;  i >= 0 ; i -- )
        B.push_back(b[i] - '0');
    C = div(B , a , r);
    for(int i = C.size() - 1 ;i >= 0 ; i --)
        cout << C[i] ;
    cout << endl  << r << endl; 
    return 0 ;
}

Guess you like

Origin blog.csdn.net/wen030803/article/details/131697834