メインコンテンツまでスキップ

チュートリアル:BigIntegerクラス

📚 Source Page

このチュートリアルでは、任意に大きな整数を扱うためのBigIntegerクラスを紹介します。BigIntegerオブジェクトは、暗号アプリケーション、大きなビットマスクが必要な場合、およびその他本当に大きな整数が必要な場所でよく使用されます。

レベル: 初級
プラットフォーム: Windows, macOS, Linux, iOS, Android
クラス: BigInteger, TextEditor, MemoryBlock

はじめに

このチュートリアルのデモプロジェクトをこちらからダウンロードしてください:PIP | ZIP。プロジェクトを解凍し、最初のヘッダファイルをProjucerで開いてください。

この手順についてサポートが必要な場合は、チュートリアル:Projucer Part 1: Projucerを始めようを参照してください。

デモプロジェクト

デモプロジェクトは、さまざまな計算の結果を表示できるシンプルなテキストコンソールを設定しています。これにより、このチュートリアルでBigIntegerクラスが実行できるいくつかの操作を実証できます。

デフォルト設定では、デモプロジェクトは値11から始まる100個の整数の系列を表示します。各新しい値は古い値に11を掛けたものです。

一連の大きな整数を表示するテストコンソール
一連の大きな整数を表示するテストコンソール

ご覧のように、BigIntegerクラスは確かに非常に大きな整数を表現できます!符号付き32ビット整数(例えば、ほとんどのコンパイラでのint型)は最大2,147,483,647までの数値を表現でき、64ビット整数(JUCEでのint64型)は「たった」9,223,372,036,854,775,807までを表現できます!

テストベッドコード

このチュートリアル全体を通して、BigIntegerクラスのさまざまな機能を実証するためにデモプロジェクトの一部を変更します。議論中のすべてのコードはMainComponentクラス内にあります。実際、すべての変更はrunExample()関数に対するものです。

void runExample()
{
logMessage ("------------------------- START --------------------------");

int base = 10;
juce::BigInteger bigInt = 11;

for (auto iteration = 0; iteration < 100; ++iteration)
{
logMessage (bigInt.toString (base));

bigInt *= 11;
}

logMessage ("----------------------- FINISHED -------------------------");
}

ここでは、BigIntegerオブジェクトが11に初期化され、for()ループの各反復で11を掛けています。logMessage()関数は単に渡された文字列をTextEditorオブジェクトに投稿します。

テストベッドコードを紹介したので、BigIntegerオブジェクトに対するいくつかの操作を試すことができます。

注記

演習:異なる開始値と乗数を試して、異なる等比数列を生成してみてください。

2進数パターン

BigIntegerクラスは2進演算もサポートしています。実際、BigIntegerクラスはビットマスクとしてよく使用されます(例えば、AudioIODeviceクラスは有効な入力および出力チャンネルを表すためにBigIntegerオブジェクトを使用します --- チュートリアル:AudioDeviceManagerクラスを参照)。以下は、値3(2進数で11)から始めて、各反復で1桁左にビットシフトしながら、BigInteger値を2進数(基数2を使用)で表示する簡単な例です:

void runExample()
{
logMessage ("------------------------- START --------------------------");

int base = 2;
juce::BigInteger bigInt = 3;

for (auto iteration = 0; iteration < 100; ++iteration)
{
logMessage (bigInt.toString (base));

bigInt = bigInt << 1;
}

logMessage ("----------------------- FINISHED -------------------------");
}

ここでは、2つの1と多くの末尾の0を含む2進数値になることがわかります:

...
11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
----------------------- FINISHED -------------------------
注記

演習:異なる開始ビットパターンを試してみてください。または、非常に大きな値から始めて、代わりに徐々に右にビットシフトしてみてください。

ビットを個別に設定およびテストすることもできます。例えば、これは最初の30個の偶数番号のビットを設定し、結果を2進数、10進数、16進数、8進数で表示します:

void runExample()
{
logMessage ("------------------------- START --------------------------");

juce::BigInteger bigInt;

for (auto bit = 0; bit < 60; bit += 2)
bigInt.setBit (bit);

logMessage (juce::String ("binary: ") + bigInt.toString (2));
logMessage (juce::String ("decimal: ") + bigInt.toString (10));
logMessage (juce::String ("hex: ") + bigInt.toString (16));
logMessage (juce::String ("octal: ") + bigInt.toString (8));

logMessage ("----------------------- FINISHED -------------------------");
}

結果は以下のようになるはずです:

------------------------- START --------------------------
binary: 10101010101010101010101010101010101010101010101010101010101
decimal: 384307168202282325
hex: 555555555555555
octal: 25252525252525252525
----------------------- FINISHED -------------------------
注記

演習:上記のコードを出発点として、異なるパターンのビットを設定してみてください。

BigIntegerオブジェクトがbool値の配列であるかのように、添字演算子を使用してBigIntegerオブジェクトのビットをテストできます。この例では、元のコードを使用して等比数列を生成し、生成された各値のビット3をテストします:

void runExample()
{
logMessage ("------------------------- START --------------------------");

int base = 10;
juce::BigInteger bigInt = 11;

for (auto iteration = 0; iteration < 100; ++iteration)
{
bool isBit3set = bigInt[3];
logMessage (bigInt.toString (base) + " : " + (isBit3set ? "Bit 3 is set" : "Bit 3 is NOT set"));

bigInt *= 11;
}

logMessage ("----------------------- FINISHED -------------------------");
}

これにより、C++の標準的なビット演算子を使用するよりもコードがはるかに読みやすくなります。BigIntegerクラスを使用してビットを設定およびテストすることが非常に簡単なので、整数が小さくても便利です!

任意のデータ

BigIntegerオブジェクトは、MemoryBlockオブジェクトを介して任意のデータとの間で変換することもできます。以下の例は、文字列をMemoryBlockオブジェクト(MemoryOutputStreamオブジェクト経由)に変換し、次にBigIntegerに変換し、最後にMemoryBlockオブジェクトを介してStringオブジェクトに戻します:

void runExample()
{
logMessage ("------------------------- START --------------------------");

juce::String originalText ("BigInteger objects are really useful for cryptography");
logMessage ("Original text: ");
logMessage (originalText);
logMessage (newLine);

juce::MemoryOutputStream originalData;
originalData << originalText;

juce::BigInteger originalInteger;
originalInteger.loadFromMemoryBlock (originalData.getMemoryBlock());

logMessage ("Original text as a BigInteger: ");
logMessage (originalInteger.toString (10));
logMessage (newLine);

juce::MemoryBlock convertedData (originalInteger.toMemoryBlock());
juce::String convertedString (convertedData.toString());

logMessage ("BigInteger converted back to a string: ");
logMessage (convertedString);

logMessage ("----------------------- FINISHED -------------------------");
}

アプリケーションのメッセージが示すように、BigIntegerオブジェクトは暗号に本当に便利です。RSAKeyクラスは、メッセージを暗号化および復号化するためにBigIntegerオブジェクトに暗号アルゴリズムを適用します。

注記

演習:上記のコードで異なる文字列を試してみてください。例えば、より長いまたは短い文字列を使用すると何が起こりますか?

まとめ

このチュートリアルでは、BigIntegerクラスを紹介しました。このチュートリアルに従った後、以下のことができるはずです:

  • BigIntegerオブジェクトを使用して整数を格納し、通常の整数と同様に算術演算を適用する。
  • BigIntegerオブジェクトを2進数、10進数、16進数、8進数で表示するための文字列に変換する。
  • BigIntegerオブジェクトの個々のビットをテストおよび設定する。
  • 文字列やその他の任意のデータをBigIntegerオブジェクトとの間で変換する。

関連項目