C++-Grundalgorithmus ① – Hochpräzise Additions- und Subtraktionsberechnung

1. Einleitung

Wenn wir Computer verwenden, um numerische Berechnungen durchzuführen, stoßen wir manchmal auf folgende Probleme: n! Was ist das genaue Ergebnis?
Wenn n kleiner als 30 ist, können wir es natürlich mit dem Rechner berechnen, der dem Computer beiliegt. Aber wenn wir auf 100! stoßen, gibt es keine Möglichkeit, das genaue Ergebnis direkt zu berechnen. Ermitteln Sie als weiteres Beispiel die Summe zweier 20.000-stelliger Zahlen.

Wie lässt sich also das Problem der fehlenden Präzision lösen?
Der hochgenaue Algorithmus ist eine mathematische Berechnungsmethode zur Verarbeitung großer Zahlen.

  • Bei allgemeinen wissenschaftlichen Berechnungen werden Berechnungen häufig mit einigen hundert Nachkommastellen oder mehr durchgeführt. Natürlich kann es sich auch um große Zahlen im Bereich von Hunderten von Milliarden bis zu mehreren zehn Milliarden handeln. Im Allgemeinen bezeichnen wir diese Art von Zahlen als hochpräzise Zahlen. Hochpräzise Algorithmen verwenden Computer, um Addition, Subtraktion, Multiplikation, Division, Potenzierung, Fakultät, Quadratwurzel und andere Operationen an sehr großen Datenmengen zu simulieren. Sehr große Zahlen können nicht normal im Computer gespeichert werden.
  • Teilen Sie diese Zahl also in eine oder vier Ziffern auf und speichern Sie sie in einem Array. Verwenden Sie ein Array, um eine Zahl darzustellen, daher wird diese Zahl als hochpräzise Zahl bezeichnet.
  • Hochpräzise Algorithmen sind Algorithmen, die verschiedene Operationen mit hochpräzisen Zahlen durchführen können. Aufgrund ihrer Besonderheit werden sie jedoch von gewöhnlichen Zahlenalgorithmen getrennt und zu ihren eigenen.
  • Bei der hochpräzisen Verarbeitung handelt es sich eigentlich um eine Simulationsmethode, die Handberechnungen simuliert. Ihr Prinzip ist das gleiche wie bei der Verwendung vertikaler Berechnungen. Während des Verarbeitungsprozesses müssen wir jedoch auf das Lesen, Konvertieren und Speichern hochpräziser Daten achten , Datenberechnung und Ergebnisbits . Verschiedene Probleme wie .

2. Hohe Präzision + niedrige Präzision

Es gibt eine große Zahl, wie zum Beispiel 999999999999999999, eine kleine Zahl 6666. Wie addiert man diese beiden Zahlen?

Hochpräzise Additionsideen

  1. Speichern Sie große Zahlen in Zeichenfolgen.

  2. Jede Zeichennummer der Zeichenfolge wird durch ASCII-Konvertierung im Array gespeichert.
    Beachten Sie, dass das Low-Bit am Anfang des Arrays vorhanden sein muss: a[i] = s[len-i-1]-'0';

  3. Berechnung für Addition und Übertrag:
    ① a[i+1] += a[i]/10;
    ② a[i] %= 10;

  4. Zahlenüberlauf, Länge +1;

  5. Ausgabeergebnisse umkehren;

Sehen wir uns am Beispiel der C++-Sprachprogrammierung an, wie wir das machen.

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

Im Code speichert das Array s1 große Zahlen und die Ganzzahl b speichert Dezimalzahlen.
① 1234 + 66
② 123456 + 99
Gemäß der mathematischen Additionsoperation werden zuerst die Einheitenziffer und die Einheitenziffer addiert, d. h.
① s1[3] + 6
② s1[5] + 9
Aus dem Obigen kann es sein gesehen, dass die Einheiten Ziffer + Einheiten Die Indexindizes der Ziffern sind inkonsistent, was die Schwierigkeit der Programmierung erhöht. Dann können Sie erwägen, das Array in umgekehrter Reihenfolge zu speichern! Die einzelne Ziffer wird am Anfang des Arrays platziert, nämlich s1[0]. Egal wie groß der Wert ist, der Array-Index beginnt mit s1[0] für die Addition.

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

Da s1 eine Zeichenfolge ist und über die ASCII-Codetabelle in eine Ganzzahl umgewandelt werden muss, muss -'0' subtrahiert werden.

Okay, oben haben wir die Speicherung der großen Zahlen im Array abgeschlossen und müssen dann die Additionsoperation ausführen.

  • Fügen Sie zuerst die Dezimalzahl zur Position a[0] hinzu: a[0] +=b;zum Beispiel 1234 + 89 =》a[0] = 1323;
  • Belassen Sie dann die neue einzelne Ziffer in a[0] und führen Sie Übertragsoperationen für andere Ziffern durch.
a[0+1] += a[0] /10; // a[1] = 3+132 = 135  
a[0] = a[0] % 10; // a[0] = 3
  • Analog dazu wird die Zehnerstelle aktualisiert und andere Stellen übernommen.
	//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;
	}

Nach der Additionsoperation muss die Situation eines Zahlenüberlaufs berücksichtigt werden; zum Beispiel hat 999 +11 == 1010 zusätzliche tausend Stellen. Die Lösung für dieses Problem ist einfach: Stellen Sie fest, ob das höchste Bit nicht 0 ist, und führen Sie die Übertragsoperation erneut aus, wenn die Bedingungen erfüllt sind!

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

Denken Sie bei der Ausgabe des Ergebnisses daran, es umzukehren, da unser a[0] zuvor das niedrigste Bit war und die Ausgabe vom High-Bit zum Low-Bit von links nach rechts erfolgt.

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

Der vollständige Code für hohe Präzision + niedrige Präzision lautet wie folgt:

#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];
	}
} 

Fügen Sie hier eine Bildbeschreibung ein


3.Hohe Präzision + hohe Präzision

Ähnliche Schritte wie oben.

Hochpräzise Additionsideen:

  1. Speichern Sie große Zahlen in Zeichenfolgen.
  2. Jede Zeichennummer der Zeichenfolge wird durch ASCII-Konvertierung im Array gespeichert.
    Beachten Sie, dass das Low-Bit am Anfang des Arrays vorhanden sein muss: a[i] = s[len-i-1]-'0';
  3. Ermitteln Sie die maximale Zahlenlänge: max(len1,len2);
  4. Berechnung für Addition und Übertrag:
    ① a[i+1] += a[i]/10;
    ② a[i] %= 10;
  5. Zahlenüberlauf, Länge +1;
  6. Ausgabeergebnisse umkehren;
#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';
	}

Beide großen Zahlen müssen in Strings gespeichert und dann in Ganzzahlen umgewandelt werden. Dann werden die Array-Indizes der Reihe nach entsprechend der Anzahl der Ziffern hinzugefügt, d. h. a[i]+b[i]. Wann das Addieren beendet werden soll, wird durch die Zahl mit der größten Länge bestimmt, daher benötigen wir vor dem Addieren die größte Zahlenlänge.

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

Durch c[i] = a[i]+b[i] kann es Situationen wie c[0] = 11 geben, die größer als 10 sind und einen Übertrag erfordern!

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

Es ist immer noch dasselbe. Nach dem Übertrag wird das Überlaufproblem berücksichtigt und dann wird die Ausgabe umgekehrt.

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

Hohe Präzision + hochpräziser vollständiger 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;
} 

Fügen Sie hier eine Bildbeschreibung ein


4. Hochpräzise Subtraktion

Auf diese Weise ist eine Subtraktion erforderlich. Wenn die Subtraktion zweier Zahlen <0 ist, sollte ein negatives „-“- Zeichen ausgegeben werden!

Die Idee der hochpräzisen Subtraktion:

  1. Geben Sie zwei große Zahlen ein;

  2. Um die Größe zu bestimmen, legen Sie fest, dass s1 immer größer als s2 ist:

  3. Ermitteln Sie die Länge.

  4. Zeichen in Ganzzahl umwandeln: a[i] = s1[len1-i-1]-'0';

  5. Subtraktionsoperation:
    ① if(a[i]<b[i]){ a[i+1]–; //oberes Bit – a[i]+=10; //unteres Bit+10 } ② c[i] = a[i]-b[i];



  6. Führende Nullen entfernen;

  7. Reverse-Ausgabe;

Schauen Sie, geben Sie den Wert ein. Der erste Wert, den Sie eingeben, stellt den Subtrahend dar, und der zweite stellt den Minuenden dar; wir wissen, dass es bei der Subtraktion negative Zahlen geben wird, also müssen wir die Situation berücksichtigen, in der der Subtrahend < der Minuend ist. Das heißt, die Länge des Subtrahends < die Länge des Minuends oder, wenn die Längen gleich sind, der Subtrahendwert < der Minuendwert. Dann geben wir das „-“-Zeichen aus und tauschen die beiden Werte aus. Machen Sie sich immer bewusst, dass der Subtrahend immer größer als der Minuend ist! ! !

#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';
	} 

Führen Sie nach der Konvertierung in eine Ganzzahl und dem Speichern im Array eine Subtraktionsoperation durch. Gemäß den Subtraktionsregeln müssen Sie +10 ausleihen, wenn die Zahl zum Subtrahieren nicht ausreicht, und wenn sie ausgeliehen ist, müssen Sie sie subtrahieren 1. Zum Beispiel 1234-66. Wenn a[0] - b[0] < 0, ist es notwendig, +10 zu leihen, also a[0] + 10, und dann b[0] zu subtrahieren; dann wird a[0+1]– geliehen;

	//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
	} 

Dabei ist zu beachten: 123 -120 = 003, die führenden Nullen müssen eliminiert werden. Dann in umgekehrter Reihenfolge ausgeben.

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

Vollständiger Code für hochpräzise Subtraktion:

/*
高精度减法的思想
	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;
} 

Fügen Sie hier eine Bildbeschreibung ein

Je suppose que tu aimes

Origine blog.csdn.net/weixin_44775255/article/details/129520783
conseillé
Classement