C++ Basic Algorithm ①——High-precision addition and subtraction calculation

1.Introduction

When we use computers to perform numerical calculations, we sometimes encounter such problems: n! What is the precise result of ?
When n is less than 30, of course we can calculate it through the calculator that comes with the computer. But when we encounter 100!, there is no way to directly calculate the accurate result. For another example, find the sum of two 20,000-digit numbers.

So how to solve the problem of missing precision?
High Accuracy Algorithm is a mathematical calculation method for processing large numbers.

  • In general scientific calculations, calculations are often made to a few hundred digits or more after the decimal point. Of course, it may also be large numbers ranging from hundreds of billions to tens of billions. Generally, we call these types of numbers high-precision numbers. High-precision algorithms use computers to simulate addition, subtraction, multiplication, division, exponentiation, factorial, square root and other operations on very large data. Very large numbers cannot be stored normally in the computer.
  • So, split this number into one digit or four digits and store it in an array. Use an array to represent a number, so this number is called a high-precision number.
  • High-precision algorithms are algorithms that can handle various operations on high-precision numbers, but because of their particularity, they are separated from ordinary number algorithms and become their own.
  • High-precision processing is actually a simulation method, which simulates hand calculation. Its principle is the same as when we use vertical calculations. However, during the processing process, we must pay attention to the reading of high-precision data, conversion and storage, data calculation, and result bits. Several issues such as number calculation and output .

2. High precision + low precision

There is a large number, such as 999999999999999999; a small number 6666. How do you add these two numbers together?

High-precision addition ideas

  1. Store large numbers into strings;

  2. Each character number of the string is stored in the array through ASCII conversion.
    Note that the low bit must exist at the beginning of the array: a[i] = s[len-i-1]-'0';

  3. Calculation for addition and carry:
    ① a[i+1] += a[i]/10;
    ② a[i] %= 10;

  4. Number overflow, length +1;

  5. Reverse output results;

Let’s see how we do it, using C++ language programming as an example.

#include<iostream>
#include<string>
using namespace std;
string s1;
int a[1000],b; 
int main(){
    
    
	cin>>s1>>b; // 1.输入数值 

In the code, the s1 array stores large numbers, and the b integer stores decimals.
① 1234 + 66
② 123456 + 99
According to the mathematical addition operation, the units digit and the units digit are added first, that is,
① s1[3] + 6
② s1[5] + 9
From the above, it can be seen that the units digit + units The index subscripts of the digits are inconsistent, which will increase the difficulty of programming. Then you can consider storing the array in reverse order! The single digit is placed at the beginning of the array, which is s1[0]. No matter how big the value is, the array subscript starts with s1[0] for addition.

//	s1存到数组a里面,记得转为整数
	int len1 = s1.size(); //获取长度
	for(int i=0;i<len1;i++){
    
    
		a[i] = s1[len1-i-1]-'0';
	} 

Because s1 is a string and needs to be converted into an integer through the ASCII code table, -'0' needs to be subtracted.

Okay, above we have completed storing the large numbers into the array, and then we need to perform the addition operation.

  • Add the decimal to the a[0] position first: a[0] +=b;for example 1234 + 89 =》a[0] = 1323;
  • Then leave the new single digit in a[0], and perform carry operations on other digits.
a[0+1] += a[0] /10; // a[1] = 3+132 = 135  
a[0] = a[0] % 10; // a[0] = 3
  • By analogy, the tens digit is updated and other digits are carried out.
	//3.进行加法运算。
	a[0]+=b; // 5+9999 10004
	//4.进位操作
	for(int i=0;i<len1;i++){
    
    
		a[i+1] += a[i] / 10;
		a[i] = a[i] % 10;
	}

After the addition operation, the number overflow situation must be considered; for example, 999 +11 == 1010 has an extra thousand digits. The solution to this problem is simple, determine whether the highest bit is not 0, and perform the carry operation again if the conditions are met!

	//5.考虑到数字溢出 
	while(a[len1]){
    
    
		a[len1+1] += a[len1]/10;
		a[len1] %= 10;
		len1++;
	} 

When outputting the result, remember to reverse it, because previously our a[0] is the lowest bit, and the output is from high bit to low bit from left to right.

	//6.反向输出
	for(int i=len1-1;i>=0;i--){
    
    
		cout<<a[i];
	}

The complete code of high precision + low precision is as follows:

#include<iostream>
#include<string>
using namespace std;
string s1;
int a[1000],b; 
int main(){
    
    
	cin>>s1>>b;
//	s1存到数组a里面,记得转为整数
	int len1 = s1.size();
	for(int i=0;i<len1;i++){
    
    
		a[i] = s1[len1-i-1]-'0';
	} 
	//3.进行加法运算。
	a[0]+=b; // 5+9999 10004
	//4.进位操作
	for(int i=0;i<len1;i++){
    
    
		a[i+1] += a[i] / 10;
		a[i] = a[i] % 10;
	}
	//5.考虑到数字溢出 
	if(a[len]){
    
    
		len++;
	} 
	//6.反向输出
	for(int i=len1-1;i>=0;i--){
    
    
		cout<<a[i];
	}
} 

Insert image description here


3.High precision + high precision

Similar steps to above.

High-precision addition ideas:

  1. Store large numbers into strings;
  2. Each character number of the string is stored in the array through ASCII conversion.
    Note that the low bit must exist at the beginning of the array: a[i] = s[len-i-1]-'0';
  3. Get the maximum number length: max(len1,len2);
  4. Calculation for addition and carry:
    ① a[i+1] += a[i]/10;
    ② a[i] %= 10;
  5. Number overflow, length +1;
  6. Reverse output results;
#include<iostream>
#include<string>
using namespace std;
string s1,s2;
int a[10000],b[10000],c[100001];
int main(){
    
    
//	1.输入值,长度 
	cin>>s1>>s2;  
	int len1 = s1.size();
	int len2 = s2.size(); 
//	2.把字符转为整数存到数组
//  注意要个位存到数组开头 
	for(int i=0;i<len1;i++){
    
    
		a[i] = s1[len1-i-1]-'0';
	} 
	for(int i=0;i<len2;i++){
    
    
		b[i] = s2[len2-i-1]-'0';
	}

Both large numbers must be stored in strings and then converted to integers. Then the array subscripts are added sequentially according to the number of digits, that is, a[i]+b[i]. When to stop adding is determined by the number with the largest length, so we require the largest number length before adding.

//	3.获取最大的数。 
	int len = max(len1,len2);
	// 对各个位数进行相加并把最新的值存到输出C里面。
	for(int i=0;i<len;i++){
    
    
		c[i]=a[i]+b[i];
	}

Through c[i] = a[i]+b[i]; there may be situations such as c[0] = 11, which is greater than 10, and a carry is required!

	//4.进位
	for(int i=0;i<len;i++){
    
    
		c[i+1] += c[i]/10;
		c[i] %= 10; 
	}

It’s still the same. After the carry, the overflow problem is taken into account, and then the output is reversed.

	//6.考虑到数字溢出 
	if(a[len]){
    
    
		len++;
	} 
	//7.反向输出 
	for(int i=len-1;i>=0;i--){
    
    
		cout<<a[i];
	}

High precision + high precision complete code:

/*
高精度的加法思想
	1.把大数存到字符串; 
	2.字符串的每个字符数字都通过ASCII转换存到数组,
	注意的是要低位存在数组开头:a[i] = s[len-i-1]-'0';
	
	3.获取最大的数长度:max(len1,len2) ;
	4.把a,b值加入到c数组: c[i] = a[i]+b[i]; 
	
	5.c数组加法进位的算式:
	①	c[i+1] += c[i]/10; 
	②  c[i] %= 10;
	
	6.数字溢出,长度+1;
	7.反向输出结果;
*/
#include<iostream>
#include<string>
using namespace std;
string s1,s2;
int a[10000],b[10000],c[100001];
int main(){
    
    
//	1.输入值,长度 
	cin>>s1>>s2;  
	int len1 = s1.size();
	int len2 = s2.size(); 
//	2.把字符转为整数存到数组
//  注意要个位存到数组开头 
	for(int i=0;i<len1;i++){
    
    
		a[i] = s1[len1-i-1]-'0';
	} 
	for(int i=0;i<len2;i++){
    
    
		b[i] = s2[len2-i-1]-'0';
	}
//	3.获取最大的数。 
	int len = max(len1,len2);
	// 对各个位数进行相加 
	for(int i=0;i<len;i++){
    
    
		c[i]=a[i]+b[i];
	}
	//4.进位
	for(int i=0;i<len;i++){
    
    
		c[i+1] += c[i]/10;
		c[i] %= 10; 
	}
	//5.溢出
	while(c[len]==0 && len>0){
    
    
		len--;
	} 
	if(c[len]>0){
    
    
		len++;
	} 
	//6.反向输出 
	for(int i=len-1;i>=0;i--){
    
    
		cout<<c[i];
	}
	return 0;
} 

Insert image description here


4. High-precision subtraction

Subtraction is required in this way. When the subtraction of two numbers is <0, a negative '-' sign should be output!

The idea of ​​high-precision subtraction:

  1. Enter two large numbers;

  2. To determine the size, fix s1 to always be greater than s2:

  3. Get the length;

  4. Convert character to integer: a[i] = s1[len1-i-1]-'0';

  5. Subtraction operation:
    ① if(a[i]<b[i]){ a[i+1]–; //upper bit – a[i]+=10; //lower bit+10 } ② c[i] = a [i]-b[i];



  6. Remove leading zeros;

  7. Reverse output;

Look, enter the value. The first one you enter represents the subtrahend, and the second one represents the minuend; we know that there will be negative numbers in subtraction, so we must consider the situation where the subtrahend < the minuend. That is, the length of the subtrahend < the length of the minuend, or if the lengths are equal, the subtrahend value < the minuend value. Then we will output the '-' sign and exchange the two values. Permanently realize that the subtrahend is always greater than the minuend! ! !

#include<iostream>
#include<string>
using namespace std;
string s1,s2;
int a[10000],b[10000],c[10000];
int main(){
    
    
//	1.输入值
	cin>>s1>>s2;
//	2.判断大小,固定s1恒大于s2 
	if(s1.size()<s2.size() || s1.size()==s2.size() && s1<s2){
    
    
		swap(s1,s2); //交换值
		cout<<"-";
	} 
//	3.获取长度
	int len1 = s1.size(); 
	int len2 = s2.size();  
//	4.字符变整数
	for(int i=0;i<len1;i++){
    
    
		a[i] = s1[len1-i-1]-'0';
	} 
	for(int i=0;i<len2;i++){
    
    
		b[i] = s2[len2-i-1]-'0';
	} 

After converting it to an integer and storing it in the array, perform a subtraction operation. According to the subtraction rules, if the number is not enough to subtract, you need to borrow +10, and if it is borrowed, you need to subtract 1. For example 1234-66. If a[0] - b[0] < 0, it is necessary to borrow +10, that is, a[0] + 10 and then subtract b[0]; then it is borrowed a[0+1]–;

	//5.减法运算 
	for(int i=0;i<len1;i++){
    
    
		if(a[i]<b[i]){
    
    
			a[i+1]--; //被借位-- 
			a[i]+=10; // 本位+10 
		}
		c[i] = a[i]-b[i];  //相减结果存到数组c
	} 

It should be noted that: 123 -120 = 003, the leading zeros must be eliminated. Then output in reverse.

	//6.去除前导零
	while(c[len1-1]==0 && len1>1){
    
    
		len1--;
	} 
	//7.反向输出
	for(int i=len1-1;i>=0;i--){
    
    
		cout<<c[i];
	} 

Complete code for high-precision subtraction:

/*
高精度减法的思想
	1.输入大数; 
	2.判断大小,固定s1恒大于s2:
	if(s1.size()<s2.size() || s1.size()==s2.size() && s1<s2){
		swap(s1,s2); //交换值
		cout<<"-";
	} 
	3.获取长度;
	4.字符变整数:a[i] = s1[len1-i-1]-'0';
	5.减法运算:
		if(a[i]<b[i]){
			a[i+1]--; //上位-- 
			a[i]+=10; // 本位+10 
		}
		c[i] = a[i]-b[i]; 

	6.去除前导零;
	while(c[len1-1]==0 && len1>1){
		len1--;
	} 
	7.反向输出;
*/
#include<iostream>
#include<string>
using namespace std;
string s1,s2;
int a[10000],b[10000],c[10000];
int main(){
    
    
//	1.输入值
	cin>>s1>>s2;
//	2.判断大小,固定s1恒大于s2 
	if(s1.size()<s2.size() || s1.size()==s2.size() && s1<s2){
    
    
		swap(s1,s2); //交换值
		cout<<"-";
	} 
//	3.获取长度
	int len1 = s1.size(); 
	int len2 = s2.size();  
//	4.字符变整数
	for(int i=0;i<len1;i++){
    
    
		a[i] = s1[len1-i-1]-'0';
	} 
	for(int i=0;i<len2;i++){
    
    
		b[i] = s2[len2-i-1]-'0';
	} 
	//5.减法运算 
	for(int i=0;i<len1;i++){
    
    
		if(a[i]<b[i]){
    
    
			a[i+1]--; //上位-- 
			a[i]+=10; // 本位+10 
		}
		c[i] = a[i]-b[i]; 
	} 
	//6去除前导零
	while(c[len1-1]==0 && len1>1){
    
    
		len1--;
	} 
	//7.反向输出
	for(int i=len1-1;i>=0;i--){
    
    
		cout<<c[i];
	} 
	
	return 0;
} 

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_44775255/article/details/129520783