それは可能だったでしょうか?はい。しかし、それには多くの問題があります。
たとえば、Javaが BigInteger への参照を格納するとします。これは実際にはヒープに割り当てられますが、intリテラルを格納します。違いはCで明確にすることができます:
int i;
BigInt* bi;
ここで、リテラルから参照に自動的に移行するには、何らかの方法でリテラルに注釈を付ける必要があります。たとえば、int の最上位ビットが設定されている場合、他のビットを何らかのテーブル ルックアップとして使用して、適切な参照を取得できます。BigInt** bi
それはまた、それがそれにオーバーフローするたびに を取得することを意味します。
もちろん、これは符号に通常使用されるビットであり、ハードウェアの命令はこれに大きく依存しています。さらに悪いことに、これを行うと、ハードウェアがオーバーフローを検出できず、それを示すフラグを設定できなくなります。その結果、各操作には、オーバーフローが発生したかどうか、または発生するかどうかを確認するための何らかのテストを伴う必要があります (いつ検出できるかによって異なります)。
基本的な整数演算に多くのオーバーヘッドが追加され、実際には、最初から必要な利点がすべて無効になります。つまり、int を使用してオーバーフロー条件を検出し、同時に参照/リテラルの問題を処理するよりも、BigInt を想定する方が高速です。
したがって、真の利点を得るには、int を表現するためにより多くのスペースを使用する必要があります。したがって、スタック、オブジェクト、またはそれらを使用する他の場所に 32 ビットを格納する代わりに、たとえば 64 ビットを格納し、追加の 32 ビットを使用して、参照またはリテラルのどちらが必要かを制御します。それはうまくいくかもしれませんが、それには明らかな問題があります - スペースの使用です。:-) とはいえ、64 ビットのハードウェアではもっと多く見られるかもしれません。
では、なぜ 64 ではなく 40 ビット (32 ビット + 1 バイト) にしないのかと疑問に思うかもしれません。基本的に、最新のハードウェアでは、パフォーマンス上の理由から 32 ビット単位でデータを格納することが望ましいため、とにかく 40 ビットを 64 ビットにパディングします。
編集
C# でこれを行う方法を考えてみましょう。現在、私は C# のプログラミング経験がないため、それを行うためのコードを書くことはできませんが、概要を説明できると思います。
アイデアは、そのための構造体を作成することです。おおよそ次のようになります。
public struct MixedInt
{
private int i;
private System.Numeric.BigInteger bi;
public MixedInt(string s)
{
bi = BigInteger.Parse(s);
if (parsed <= int.MaxValue && parsed => int.MinValue)
{
i = (int32) parsed;
bi = 0;
}
}
// Define all required operations
}
したがって、数値が整数の範囲内にある場合は int を使用し、それ以外の場合は BigInteger を使用します。操作は、必要に応じて/可能な限り、ある操作から別の操作への移行を保証する必要があります。クライアントの観点からは、これは透過的です。これは MixedInt 型の 1 つにすぎず、クラスはより適したものを使用します。
ただし、構造体として実装されていることを考えると、この種の最適化は C# の BigInteger の一部である可能性があることに注意してください。
Java に C# の構造体のようなものがあれば、Java でもこのようなことができます。