C++の基本アルゴリズム② ~高精度な乗除算~

C++基本アルゴリズム①——高精度な加減算

高精度の加算と減算をすでに知っている場合は、乗算と除算を検討するのがはるかに簡単になります。それでは、最初に乗算について見てみましょう。乗算のルールは、2 つの数値を 1 つずつ乗算し、それらを加算して最終結果を得るというものです。実際には、高精度の加算の前に乗算演算を実行します。

高精度加算のアイデア:

  1. 大きな数値を文字列に格納します
  2. 2 つの数値を乗算する長さを求めます。2 つの数値の乗算の最大長は、2 つの数値の長さの合計を超えません。len_max = len1+len2-1;
  3. 文字列の各文字番号は、ASCII 変換を通じて配列に格納されます
    下位ビットは配列の先頭に存在する必要があることに注意してください: a[i] = s[len-i-1]-'0';
  4. 乗算と桁上げの計算式
    ① c[i+j] += a[i] * b[j]
  5. 配列 c にキャリーを追加します:
    ① c[i+1] += c[i]/10;
    ② c[i] %= 10;
  6. 結果のオーバーフロー
  7. 出力結果を反転します。

1. 高精度と低精度を掛ける

値を入力して配列に格納し、整数に変換します。

#include<iostream>
#include<string>
using namespace std;
string a;
int b[100],c;
int main(){
    
    
	cin >> a >> c;
	//把a 存储到 b里面去,a的最低位存储到b[0]
	int lena = a.size();
	for(int i=0; i<lena; i++){
    
    
		b[i] = a[lena-1-i] - '0';
	} 

乗算: 1234 * 5、5 は各数値を個別に乗算することがわかります (b[0] * 5、b[1] * 5 など)。

//把c依次乘到b数组的每一位
	for(int i=0; i<lena; i++){
    
    
		b[i] *= c;
	} 

乗算後、配列の値が 9 を超える場合は、繰り上げなければなりません。

	//处理进位
	for(int i=0; i<lena; i++){
    
    
		b[i+1] += b[i]/10;
		b[i] %= 10;
	}

たとえば、9999 * 9 = 89991 の場合、オーバーフローしたため処理する必要があります。最後に、結果を逆に出力することを忘れないでください。

//高位处理,对象是b[lena] ,利用数位分离的方法
	while(b[lena]){
    
    
		b[lena+1] = b[lena]/10;
		b[lena] %= 10;
		lena++;//这里容易漏掉 
	}
//反向输出 
	for(int i=lena-1; i>=0; i--){
    
    
		cout << b[i];
	} 
	return 0;
} 

高精度* 低精度の完全なコード:

#include<iostream>
#include<string>
using namespace std;
string a;
int b[100],c;
int main(){
    
    
	cin >> a >> c;
	//把a 存储到 b里面去,a的最低位存储到b[0]
	int lena = a.size();
	for(int i=0; i<lena; i++){
    
    
		b[i] = a[lena-1-i] - '0';
	} 
	//把c依次乘到b数组的每一位
	for(int i=0; i<lena; i++){
    
    
		b[i] *= c;
	} 
	//处理进位
	for(int i=0; i<lena; i++){
    
    
		b[i+1] += b[i]/10;
		b[i] %= 10;
	} 
	//高位处理,对象是b[lena] ,利用数位分离的方法
	while(b[lena]){
    
    
		b[lena+1] = b[lena]/10;
		b[lena] %= 10;
		lena++;//这里容易漏掉 
	} 
	//反向输出 
	for(int i=lena-1; i>=0; i--){
    
    
		cout << b[i];
	} 
	return 0;
} 

ここに画像の説明を挿入します


2. 高精度と高精度を掛け合わせる

基本的には前と同じで、入力を整数に変換して配列に格納します。

#include<iostream>
#include<string>
using namespace std;
string s1,s2;
int a[100],b[100],c[200];
int main(){
    
    
	cin>>s1>>s2;
	int len1 = s1.size(); 
	int len2 = s2.size(); 
	int len_max = len1+len2-1; //
	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';
	}

全長はどうやって求めるのですか?
1. 2 つの数値を掛けます (0 は考慮しません)。一般に、全長は **[2 つの数値の長さの合計 -1、2 つの数値の長さの合計]** です。この区間では、I len_max = len1+len2-1を設定します。

垂直乗算と垂直加算

ここに画像の説明を挿入します
こう見ると、配列 a の添字は i、配列 b の添字は j で表され、配列 c の場合、 c[1+0] = a[1]* であることがわかります。 b[0] + a[0]* b[1] ; 導出: c[i+j] += a[i] * b[j]

// 乘法
	for(int i=0;i<len1;i++){
    
    
		for(int j=0;j<len2;j++){
    
    
			c[i+j] += a[i] * b[j]; 
		}
	}

乗算後、c 配列の値が 9 を超える場合は、加算と桁上げが行われます。

	for(int i=0;i<len_max;i++){
    
    
		c[i+1] += c[i]/10;
		c[i] %= 10;
	}

キャリー終了後、オーバーフローがないか確認し、最後に結果を反転出力します。

//溢出处理,再加法进位一次
	while(c[len_max]){
    
    
		c[len_max+1] = c[len_max]/10;
		c[len_max] %= 10;
		len_max++;
	} 
//反向输出
	for(int i=len_max-1;i>=0;i--){
    
    
		cout<<c[i];
	} 

ここに画像の説明を挿入します


3. 高精度で低精度を解消

ここに画像の説明を挿入します
上の図からわかるように、最初の 4 と 23 は一致します。つまり、最上位の桁を 23 で割ります。配列が格納される場合、a[0] が最上位ビットになります。

#include<iostream>
#include<string>
using namespace std;
string s;
int a[1000],b,c[10000],x=0;
int main(){
    
    
	cin>>s>>b; 
	int len = s.size(); 
	for(int i=0;i<len;i++){
    
    
		a[i] = s[i]-'0'; //最高位存a[0]
	}

ここに画像の説明を挿入します
整数 0 と余り 4 を取得するにはどうすればよいですか?

整数:c[0] = a[0] / b
余数:? = a[0] % b

整数 1 と余り 45 を取得するにはどうすればよいでしょうか?

整数:c[1] = (a[0]*10+a[1]) / b;
余数:? =  (a[0]*10+a[1]) % b;

a[0] * 10 これは x * 10 で表すことができ、余りは x で表されます。

	// 除法
	for(int i=0;i<len;i++){
    
    
		c[i] = (x*10+a[i]) / b;
		x = (x*10+a[i]) % b;
	}

このようにして、c[i]には除算の結果の商が格納されます。例: 4567 / 23 = 0198 ... 13。
配列 c の結果が 0 であることがわかります。どうやって取り出すのでしょうか?乗算時には len– メソッドを使用してそれを取り出し、除算には len++ を使用します; 先頭の 0 が無視されるように c 配列のインデックスを 1 つ前に戻します。

	// 去除前导〇
	int lenc=0;
	while(c[lenc]==0 && lenc<len){
    
    
		lenc++;
	}

最終出力では、インデックスの先頭が lenc! から始まる必要があります。

	for(int i=lenc;i<len;i++){
    
    
		cout<<c[i];
	}

高値で低値を除算するための完全なコード:

#include<iostream>
#include<string>
using namespace std;
string s;
int a[1000],b,c[10000],x=0;
int main(){
    
    
	cin>>s>>b;
	int len = s.size(); 
	for(int i=0;i<len;i++){
    
    
		a[i] = s[i]-'0';
	}
	for(int i=0;i<len;i++){
    
    
		c[i] = (x*10+a[i]) / b;
		x = (x*10+a[i]) % b;
	}
	int lenc=0;
	while(c[lenc]==0 && lenc<len){
    
    
		lenc++;
	}
	for(int i=lenc;i<len;i++){
    
    
		cout<<c[i];
	}
	return 0;
}

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/weixin_44775255/article/details/129527957