Four operations of large numbers
High precision calculation means that the number involved in the operation is far beyond the range of standard data types, such as multiplication of two 1000 digits, which occurs frequently in algorithm competitions. In c or c + +, the maximum data type is only 64 bits. If a larger number needs to be processed, it can only be simulated by an array. Each bit of the large number can be stored in an array, and then carry and borrow bits can be processed by bits.
I searched some data on the Internet and found that what I wrote was too tedious and difficult to understand. I wrote four operations for large numbers (division is not written for the time being, but it will be updated tomorrow). The code is as follows.
First define a structure
typedef struct aaa{ int num[MAXN]; //The high and low bits store your numbers in reverse int len; //Number of digits aaa(){memset(num,0,sizeof(num));len=-1;} //Constructor }bignum;
Note that there is a num [] array in the structure, and the high and low order of the stored numbers are opposite, for example, 1234. In the array, it is actually num[0]=4,num[1]=3,num[2]=2,num[3]=1, which is helpful for the subsequent operation, because the addition and subtraction methods start from the low order. len represents the number of digits in the number.
A function that converts a string to a large number
bignum change_bignum(char *s){ bignum tmp; int length=strlen(s); for(int i=0;i<strlen(s);i++) tmp.num[length-1-i]=s[i]-48; //High position in front, low position in front, convenient for operation tmp.len=length; return tmp; }
The parameter of this function is a character pointer. In the main function, as long as the value is assigned in the character array, you can call the change ﹣ bignum() function, and then return a bignum type structure. Again, the high and low order of large numbers are the opposite.
Print large functions
void show(bignum a){ //Print digit for(int i=a.len-1;i>=0;i--) printf("%d",a.num[i]); printf("\n"); }
Note that even after the operation is completed, it can only be output through the array, because even the long long is not so large. (subtraction, division may get a small number, but it's special)
When the preparation is finished, you can do the calculation.
Addition operation
bignum add(bignum a,bignum b){ bignum tmp; int carry=0; //Carry information int length=max(a.len,b.len); //Maximum number of digits of two numbers for(int i=0;i<length;i++){ tmp.num[i]=(a.num[i]+b.num[i]+carry)%10; //Store the number after operation carry=(a.num[i]+b.num[i]+carry)/10; //Update carry information } if(carry){ //If there is carry after the last operation tmp.num[length]=carry; //The highest digit is the carry digit tmp.len=length+1; //New digits plus 1 } else tmp.len=length; //Number of new digits return tmp; }
The idea is to add from the low order. If it is greater than 10, carry information will be stored with carry, and then the result of adding mod10 will exist in the corresponding position. If the result of addition is greater than 10, carry can directly assign 1. Why? Because two numbers less than 10 are added, the maximum is 18, and only one digit can be added. But it is better to divide 10 by the result of addition, because in the later multiplication operation, carry information may be 2, 3, 4 For example, 7 * 7, 4. The last if, else to assign a length to a new large number, generally speaking, is the one with the most median of two addends, but after adding two numbers with the same number of digits, carry information may be generated in the highest position, so you need to add the length of the large number by one bit, such as 77 + 66.
Subtraction operation
bignum Minus(bignum a,bignum b){ //a is bigger than b. bignum tmp; for(int i=0;i<a.len;i++){ if(a.num[i]<b.num[i]){ int borrow=1; //Borrow information while(a.num[i+borrow]==0) //The high order is 0 until you find a number to borrow borrow++; a.num[i+borrow]--; //Number of borrowed digits minus 1 a.num[i]+=10; //Borrow digit plus 10 for(int j=i+1;j<i+borrow;j++){ //Change the high order of those 0's a.num[j]=9; } } tmp.num[i]=a.num[i]-b.num[i]; } for(int i=a.len-1;i>=0;i--) //Find the number whose first highest digit is not 0 as the highest digit of the new number if(tmp.num[i]!=0){ tmp.len=i+1; //Number of new digits break; } return tmp; }
Subtraction is more complicated than addition (for example, division is more difficult than multiplication. The blogger hasn't written it out yet, and it will be updated tomorrow)
Addition has carry, subtraction has borrow, addition starts from the lowest, subtraction also starts from the lowest. If the low value of the subtracted digit is smaller than the low value of the subtracted digit, it needs to borrow 1 from the high position. If the high position is 0, it needs to borrow from the next higher position until the high position is non-zero. Then add 10 to the position number of the borrow position and subtract 1 from the digit value of the borrowed position. In the middle of the process, all the bits of 0 become 9 (better than 1001-9). When the borrow position is good, it can be calculated. After the operation is completed, traverse from high to low to find the first non-zero bit, so that the number of new digits can be determined.
Multiplication operation
The multiplication of large numbers is the same as that of primary schools. The column vertical calculation is as shown in the figure above.
bignum multiply(bignum a,bignum b){ //Column calculation bignum tmp; int carry=0; for(int i=0;i<b.len;i++){ //Every one of b for(int j=0;j<a.len;j++){ //Everyone of a tmp.num[i+j]+=(b.num[i]*a.num[j]+carry)%10; //Multiplication as shift addition carry=(b.num[i]*a.num[j]+carry)/10; if(tmp.num[i+j]>=10){ //Vertical accumulation may also produce carry tmp.num[i+j]-=10; //Here, the result of each operation is added directly to the number on the corresponding digit carry++; //Generating carry directly gives the next bit of this vertical calculation without affecting the final result } } } if(carry){ //Similarly, if the carry is generated by the highest order operation of two numbers, the number of digits of the new number will be increased by 1 tmp.num[a.len-1+b.len]=carry; tmp.len=a.len+b.len; } else tmp.len=a.len-1+b.len; //Otherwise, think about 1000 * 100 and 300 * 400 return tmp; }
The first row of numbers is assumed to be a, the second row is b, and each bit of b is multiplied by each bit of a, so there are two layers of loops. Note that the weights of each digit of a and b are different, for example, the second digit of a, 2, and the first digit of b, 4. The result of multiplication should be saved in ten digits. The result of multiplication of the i-th digit of a and the j-th digit of b should be saved in the i+j-th digit of the new number (note here that num[0] is a digit number. To generalize, num[i] is an i+1 digit number). You can find several numbers to verify it. Note also that there are two carry information here, one is the carry obtained by multiplying each bit of a and b, and the other is the carry generated by adding the intermediate results of two multiplication (pink in the figure). After explanation, the above code is easy to understand.
The complete code is as follows (large divisor is not available for now, it will be updated tomorrow)
#include<bits/stdc++.h> using namespace std; const int MAXN=1000; typedef struct aaa{ int num[MAXN]; //The high and low bits store your numbers in reverse int len; //Number of digits aaa(){memset(num,0,sizeof(num));len=-1;} //Constructor }bignum; bignum change_bignum(char *s){ bignum tmp; int length=strlen(s); for(int i=0;i<strlen(s);i++) tmp.num[length-1-i]=s[i]-48; //High position in front, low position in front, convenient for operation tmp.len=length; return tmp; } bignum add(bignum a,bignum b){ bignum tmp; int carry=0; //Carry information int length=max(a.len,b.len); //Maximum number of digits of two numbers for(int i=0;i<length;i++){ tmp.num[i]=(a.num[i]+b.num[i]+carry)%10; //Store the number after operation carry=(a.num[i]+b.num[i]+carry)/10; //Update carry information } if(carry){ //If there is carry after the last operation tmp.num[length]=carry; //The highest digit is the carry digit tmp.len=length+1; //New digits plus 1 } else tmp.len=length; //Number of new digits return tmp; } bignum Minus(bignum a,bignum b){ //a is bigger than b. bignum tmp; for(int i=0;i<a.len;i++){ if(a.num[i]<b.num[i]){ int borrow=1; //Borrow information while(a.num[i+borrow]==0) //The high order is 0 until you find a number to borrow borrow++; a.num[i+borrow]--; //Number of borrowed digits minus 1 a.num[i]+=10; //Borrow digit plus 10 for(int j=i+1;j<i+borrow;j++){ //Change the high order of those 0's a.num[j]=9; //For example, the tens of 101-99 101 become 9 } } tmp.num[i]=a.num[i]-b.num[i]; } for(int i=a.len-1;i>=0;i--) //Find the number whose first highest digit is not 0 as the highest digit of the new number if(tmp.num[i]!=0){ tmp.len=i+1; //Number of new digits break; } return tmp; } void show(bignum a){ //Print digit for(int i=a.len-1;i>=0;i--) printf("%d",a.num[i]); printf("\n"); } bignum multiply(bignum a,bignum b){ //Column calculation bignum tmp; int carry=0; for(int i=0;i<b.len;i++){ //Every one of b for(int j=0;j<a.len;j++){ //Everyone of a tmp.num[i+j]+=(b.num[i]*a.num[j]+carry)%10; //Multiplication as shift addition carry=(b.num[i]*a.num[j]+carry)/10; if(tmp.num[i+j]>=10){ //Vertical accumulation may also produce carry tmp.num[i+j]-=10; //Here, the result of each operation is added directly to the number on the corresponding digit carry++; //Generating carry directly gives the next bit of this vertical calculation without affecting the final result } } } if(carry){ //Similarly, if the carry is generated by the highest order operation of two numbers, the number of digits of the new number will be increased by 1 tmp.num[a.len-1+b.len]=carry; tmp.len=a.len+b.len; } else tmp.len=a.len-1+b.len; //Otherwise, think about 1000 * 100 and 300 * 400 return tmp; } int main(){ bignum a,b,result; char s[MAXN]; scanf("%s",s); a=change_bignum(s); scanf("%s",s); b=change_bignum(s); result=add(a,b); show(result); result=multiply(a,b); show(result); result=Minus(a,b); show(result); return 0; }