これが最適化されているかどうかはわかりませんが、このコードはToByteArrayより16倍高速であるように見えます。また、メモリコピーを回避し、バイトではなくuintとして結果を取得することを意味するため、そこでさらに改善する必要があります。
//create delegate to get private _bit field
var par = Expression.Parameter(typeof(BigInteger));
var bits = Expression.Field(par, "_bits");
var lambda = Expression.Lambda(bits, par);
var func = (Func<BigInteger, uint[]>)lambda.Compile();
//test call our delegate
var bigint = BigInteger.Parse("3498574578238348969856895698745697868975687978");
int time = Environment.TickCount;
for (int y = 0; y < 10000000; y++)
{
var x = func(bigint);
}
Console.WriteLine(Environment.TickCount - time);
//compare time to ToByteArray
time = Environment.TickCount;
for (int y = 0; y < 10000000; y++)
{
var x = bigint.ToByteArray();
}
Console.WriteLine(Environment.TickCount - time);
そこから上位2ビットを見つけるのは非常に簡単です。最初のビットは私が推測する最初のintにあり、それから2番目に上位のビットを検索するだけです。同じ整数の場合は、最初のビットをゼロに設定して最上位ビットを検索します。それ以外の場合は、次のゼロなしintを検索して、最上位ビットを検索します。
編集:物事を簡単にするには、このクラスをコピーしてプロジェクトに貼り付けるだけです。これにより、拡張メソッドが作成されます。つまり、mybigint.GetUnderlyingBitsArray()を呼び出すだけです。サインを取得するメソッドも追加し、より一般的にするために、任意のオブジェクトの任意のプライベートフィールドにアクセスできるようにする関数を作成しました。これは、デバッグモードでは元のコードよりも低速ですが、リリースモードでは同じ速度であることがわかりました。これを自分でパフォーマンステストすることをお勧めします。
static class BigIntegerEx
{
private static Func<BigInteger, uint[]> getUnderlyingBitsArray;
private static Func<BigInteger, int> getUnderlyingSign;
static BigIntegerEx()
{
getUnderlyingBitsArray = CompileFuncToGetPrivateField<BigInteger, uint[]>("_bits");
getUnderlyingSign = CompileFuncToGetPrivateField<BigInteger, int>("_sign");
}
private static Func<TObject, TField> CompileFuncToGetPrivateField<TObject, TField>(string fieldName)
{
var par = Expression.Parameter(typeof(TObject));
var field = Expression.Field(par, fieldName);
var lambda = Expression.Lambda(field, par);
return (Func<TObject, TField>)lambda.Compile();
}
public static uint[] GetUnderlyingBitsArray(this BigInteger source)
{
return getUnderlyingBitsArray(source);
}
public static int GetUnderlyingSign(this BigInteger source)
{
return getUnderlyingSign(source);
}
}