これを読めば、大きな整数の乗算と分割統治アルゴリズムを学ぶことができます。

これを読めば、大きな整数の乗算と分割統治アルゴリズムを学ぶことができます。

[[352004]]

データ暗号化処理には多くの複雑な暗号化アルゴリズムがあり、これらの暗号化アルゴリズムでは非常に大きな整数演算が多数使用されることがよくあります。しかし、プログラミング言語にはデータのサイズに一定の制限があり、データが大きすぎるとデータオーバーフローが発生し、大きな整数データの操作が実行できなくなります。この記事では、大きな整数に対するデータ操作を実装する方法を学びます。この記事のコードは C++ を使用して実装します。

一般的な乗算演算

掛け算の計算には比較的簡単でわかりやすい方法があります。小学校で習った縦割りの計算法を使って掛け算の計算をすることができます。

垂直乗算

上図の列計算方法を参考にコードを実装します。

  1. #include <iostream>
  2. #include <文字列>
  3. #include <stdlib.h>
  4. #include <ベクター>
  5. #include <cstring>
  6. #include <アルゴリズム>
  7.  
  8. std::string を乗算します (std::string a、std::string b)
  9. {
  10. std::string 結果 = "" ;
  11. int行 = b.size ( );
  12. サイズを整数にする
  13. int tmp[行][列];
  14. memset(tmp,0,sizeof( int )*row*col);
  15.      
  16. 逆順( a.begin (),a.end ( ));
  17. 逆順( b.begin (),b.end ( ));
  18.      
  19. ( int i = 0; i < b.size ( ) ); i++)の場合
  20. {
  21. ( int j = 0; j < a.size ( ) ); j++)の場合
  22. {
  23. std::string bit_a = std::string(1, a.at (j));
  24. std::string bit_b = std::string(1, b.at (i));
  25.              
  26. tmp[i][j] += std::stoi(bit_a) * std::stoi(bit_b);
  27.          
  28. tmp[i][j+1] = tmp[i][j] / 10;
  29. tmp[i][j] % = 10;
  30.  
  31. }
  32.  
  33. }
  34.  
  35. int N = a.size ( ) + b.size ( );
  36. 整数 合計[N];
  37. memset(合計, 0, sizeof( int )*N);
  38.      
  39. ( int n = 0; n < N; n++)の場合
  40. {
  41. 整数i = 0;
  42. 整数j = n;
  43.          
  44. i <= n && j >= 0 の場合
  45. {
  46. if(i < 行 && j < 列)
  47. {
  48. 合計[n] += tmp[i][j];
  49. }
  50.              
  51. 私は++;
  52. j --;  
  53. }
  54.  
  55. (n+1 < N)の場合
  56. {
  57. 合計[n+1] =合計[n] / 10;
  58. 合計[n] %= 10;
  59. }
  60.  
  61. }
  62.  
  63. ブールゼロ開始フラグ = true ;
  64. ( int i = N-1; i >= 0; i --)の場合 
  65. {
  66. if(合計[i] = = 0 && ゼロ開始フラグ)
  67. {
  68. 続く;
  69. }
  70.          
  71. ゼロ開始フラグ = false ;
  72. 結果を追加します(std::to_string(合計[i]));
  73. }
  74.      
  75. 結果を返します
  76. }
  77.  
  78.  
  79. intメイン()
  80. {
  81. std::string a = "3456" ;
  82. std::string b = "1234" ;
  83.  
  84. std::string 結果 = multiply(a, b);
  85. std::cout << a << " * " << b << " = " << 結果 <<std::endl;
  86.      
  87. 0を返します
  88. }

便宜上、最初に各乗数を反転し、最後に結果を反転します。計算処理では、乗算結果を格納する配列を同じ列にシフトして加算するのではなく、斜めに加算することで、スペースと計算ステップを削減できます。上記のコードを実行した結果は以下のようになります。

運用結果

文字列の長さには特別な制限がないため、上記のアルゴリズムは大きな整数演算に適用できます。

分割統治アルゴリズム

上記の垂直列方式は大きな整数の乗算の問題を非常にうまく解決できますが、より効率的な方法である分割統治アルゴリズムを選択することもできます。クイックソートやバイナリサーチなど、多くの分野に応用できる非常に重要なアルゴリズムです。アルゴリズムの名前から、大きな問題を小さな問題に分割し、最初に小さな問題を解決してから最後にこの問題を解決することがわかります。そのため、分割統治法と呼ばれています。ここで、この方法を使用して、大きな整数をプログラミング言語を使用して直接計算できる小さな整数に分割し、最終的に大きな整数の値を取得できます。

2 つの大きな整数があるとします。これを a (サイズは n ビット) と b (サイズは m ビット) と設定します。ここではバイナリ検索法を使用してデータを分割します。これら 2 つの整数は次のように分解できます。

しかし、

作る、

上記の式によれば、a*b を 4 つの小さな整数の乗算、つまり 4 つの式 z3、z2、z1、z0 に分解できます。分解された乗算値がまだ大きい場合は、コンピュータープログラミング言語が直接計算できるようになるまで、同じ方法で分解を続け、より小さな乗算値に分解することができます。

例えば、上記の 3456 と 1234 を掛け合わせる場合、下の図を参考にして、バイナリ検索で整数を段階的に分割します。計算のために、2 つの整数を 1 桁の整数に分割します。

3456 と 1234 の分割手順図

次に、分割統治アルゴリズムのコード実装を見てみましょう。ここでは再帰的な方法を使用します。

  1. #include <iostream>
  2. #include <文字列>
  3. #include <stdlib.h>
  4. #include <ベクター>
  5. #include <cstring>
  6. #include <アルゴリズム>
  7. #include <cmath>
  8.  
  9. std::stringを追加します(std::string a、std::string b)
  10. {
  11. int N = std:: max ( a.size (), b.size ( ));
  12. 整数 合計[N];
  13. memset(合計, 0, sizeof( int )*N);
  14.      
  15. 逆順( a.begin (),a.end ( ));
  16. 逆順( b.begin (),b.end ( ));
  17.  
  18. ( int i = 0; i< N; i++)の場合
  19. {
  20. 整数ビットa = 0;
  21. ビットb = 0;
  22. i < a.size () の場合、 bit_a = std::stoi(std::string(1, a.at ( i)));
  23. i < b.size () の場合、bit_b = std::stoi(std::string(1, b.at ( i)));
  24.  
  25. 合計[i] += (bit_a + bit_b);
  26.  
  27. i < N-1 &&合計[i]>9 の場合
  28. {
  29. 合計[i+1] =合計[i] / 10;
  30. 合計[i] %=10;
  31. }
  32. }
  33.  
  34. std::string 結果 = "" ;
  35. ブールゼロ開始フラグ = true ;
  36. ( int i = N-1; i >= 0; i --)の場合 
  37. {
  38. if(合計[i] = = 0 && ゼロ開始フラグ)
  39. {
  40. 続く;
  41. }
  42.          
  43. ゼロ開始フラグ = false ;
  44. 結果を追加します(std::to_string(合計[i]));
  45. }
  46.  
  47.  
  48. 結果を返します
  49. }
  50.  
  51. std::string の分割と征服 (std::string a、std::string b)
  52. {
  53. a.size () < 2 && b.size ( ) < 2の場合
  54. {
  55. std::to_string(std::stoi(a) * std::stoi(b))を返します
  56. }
  57.      
  58. int n = a.size ( );
  59. b.size ( ) は、文字列の先頭に0 を付加します。
  60.      
  61. 整数半分N = n/2;
  62. 整数半分M = m/2;
  63.  
  64. std::string a0 = "0" ;
  65. std::string a1 = "0" ;
  66. if( a.size () > halfN && halfN > 0)
  67. {
  68. a1 = a.substr(0, 半分N);
  69. a0 = a.substr(halfN, a.size () - halfN);
  70. }
  71. それ以外 
  72. {
  73. a1 = "0" ;
  74. 0 = 0;
  75. }
  76.      
  77. std::string b0 = "0" ;
  78. std::string b1 = "0" ;
  79. b.size () > halfM && halfM > 0の場合
  80. {
  81. b1 = b.substr(0, halfM);
  82. b0 = b.substr(halfM, b.size () - halfM);
  83.  
  84. }
  85. それ以外 
  86. {
  87. b1 = "0" ;
  88. 0 = 0;
  89. }
  90.  
  91. std::string a1b1 = 分割して征服します(a1、b1);
  92. std::string a0b0 = 分割して征服する(a0, b0);
  93. std::string a1b0 = 分割して征服する(a1、b0);
  94. std::string a0b1 = 分割して征服します(a0、b1);
  95.      
  96. a1b1.append((n - 半分N) + (m - 半分M), '0' );
  97. a1b0.append(n - 半分のN、 '0' );
  98. a0b1.append(m - halfM, '0' );
  99.  
  100. std::string 結果 = "" ;
  101. 結果 = (a1b1, a1b0)を追加します
  102. 結果 =追加(結果、a0b1);
  103. 結果 =追加(結果、a0b0);
  104.  
  105. 結果を返します
  106. }
  107.  
  108. intメイン()
  109. {
  110. std::string a = "3456" ;
  111. std::string b = "1234" ;
  112.  
  113. std::cout << a << " * " << b << " = " <<divideAndConquer(a, b) << std::endl;
  114.  
  115. 0を返します
  116. }

プログラムの実行結果は次のとおりです。

分割統治アルゴリズムの演算結果

この記事はWeChat公式アカウント「Will's Canteen」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合は、Will’s Dashitang パブリックアカウントにご連絡ください。

<<:  機械学習が金融業界にもたらす破壊的変化

>>:  韓国初のAI女性キャスターが誕生。本物と間違えられ議論を巻き起こす。AIサベイニングはすでに存在していた

ブログ    
ブログ    
ブログ    
ブログ    
ブログ    

推薦する

...

ウェブページを出力できるAIアプリが登場、早速評価してみよう

みなさんこんにちは、カソンです。最近、ウェブページ作成ツールframer[1]は、プロンプトワードに...

...

Google、一般的な皮膚疾患を識別するための新しいAIツールを発表

5月19日、海外メディアの報道によると、人工知能はヘルスケア分野で多くの用途があるため、Google...

...

人工知能とブロックチェーン技術は芸術をどのように解放できるのでしょうか?

2022年において、アートがテクノロジーから切り離されていることを想像するのは難しいです。 AI、...

...

人工知能に関する学習体験のまとめ

序文今は知識が急速に反復される時代です。この時代では、次のように感じるかもしれません。「最初から最後...

...

面白いですね!プログラマーが AI を使って双子の息子を認識するんです! 「この Raspberry Pi の顔認識システムは私のものほど正確ではありません」

2021年までに、学習アルゴリズムと人工知能の研究を通じて、機械は多くの面で人間よりも優れていると...

エヌビディアのCEOが主権的AIインフラの必要性を訴える

人工知能(AI)ブームにより、Nvidiaの株価は史上最高値に達した。 Nvidia の GPU は...

シンプルな人工ニューラル ネットワークをゼロから構築する: 1 つの隠れ層

[51CTO.com クイック翻訳] 前回の記事「人工ニューラルネットワークをゼロから構築する(パー...

USTCのニューラルネットワークとエンドツーエンドのトレーニングフレームワークは、教育環境が学生の能力に与える影響を調査する

[[424271]]中国科学技術大学の研究者らは、教育コンテキスト認識型認知診断フレームワークを提案...

9つの主要テーマ!機械学習アルゴリズム理論に関する面接の質問の要約

[[342976]]機械学習は、強力な理論的側面と実践的側面を備えた技術分野です。機械学習関連の仕事...