BitArrayの最終セットビットを取得するのに有効な(高速)方法は何ですか? (LINQまたは単純な逆ループは大規模なビットマップではあまり速くないので速くする必要があります)BitArray 次のアルゴリズムを参照してください:BitArrayの内部int配列データを元に戻し、コンパイラを使用する組み込み関数C++のように_BitScanReverse C#で)。BitArrayの最終セットビットを取得するには?
答えて
"正常な" 解決策:
static long FindLastSetBit(BitArray array)
{
for (int i = array.Length - 1; i >= 0; i--)
{
if (array[i])
{
return i;
}
}
return -1;
}
反射溶液(ノート - BitArray
の実装に依存しています):
static long FindLastSetBitReflection(BitArray array)
{
int[] intArray = (int[])array.GetType().GetField("m_array", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(array);
for (var i = intArray.Length - 1; i >= 0; i--)
{
var b = intArray[i];
if (b != 0)
{
var pos = (i << 5) + 31;
for (int bit = 31; bit >= 0; bit--)
{
if ((b & (1 << bit)) != 0)
return pos;
pos--;
}
return pos;
}
}
return -1;
}
反射ソリューションは、大規模なBitArray
に私のため50-100x高速であります非常に小さなものでは、反射のオーバーヘッドが現れ始めます。私のマシンでは1メガバイトあたり約0.2msかかります。
主なことは、if (b != 0)
が一度に32ビットをチェックすることです。特定のビットをチェックする内部ループは、正しい単語が見つかったときに1回だけ実行されます。
編集済み:安全性の低いコードは、ほとんど何も得られなかったために削除されました。配列の境界チェックだけが回避され、コードはすでに非常に速いので、それほど重要ではありません。記録のために、危険な溶液(〜30%速く私のために):
static unsafe long FindLastSetBitUnsafe(BitArray array)
{
int[] intArray = (int[])array.GetType().GetField("m_array", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(array);
fixed (int* buffer = intArray)
{
for (var i = intArray.Length - 1; i >= 0; i--)
{
var b = buffer[i];
if (b != 0)
{
var pos = (i << 5) + 31;
for (int bit = 31; bit >= 0; bit--)
{
if ((b & (1 << bit)) != 0)
return pos;
pos--;
}
return pos;
}
}
}
return -1;
}
は、あなたがその最後のセットビットのインデックスをしたい場合は、C#でこれを行うことができます6.
int? index = array.Select((b,i)=>{Index = i, Value = b})
.LastOrDefault(x => x.Value)
?.Index;
そうしないと、この
var last = array.Select((b,i)=>{Index = i, Value = b})
.LastOrDefault(x => x.Value);
int? index = last == null ? (int?)null : last.Index;
ようindex
がされるいずれかの方法を何かをしなければなりませんnull
すべてのビットがゼロの場合。
Linqは高速ではありません。私は悲しい - "効果的"。 LINQはありません! –
@BransDs "effective"は主観的です。より具体的な回答が必要な場合は、より具体的に説明する必要があります。いずれにしても、Linqとまったく同じBitArrayをループする必要があります。それ以外の場合は、ビット演算子を使用する場合は、 'BitArray'よりもプリミティブ型を使用する必要があります。 – juharr
最後から最初のビットまで繰り返す以外に何かできるとは思っていません。設定されていれば、それぞれを尋ねます。
BitArray bits = ...;
int lastSet = Enumerable.Range(1, bits.Length)
.Select(i => bits.Length - i)
.Where(i => bits[i])
.DefaultIfEmpty(-1)
.First();
最後のビットが返されます。存在しない場合は-1、そうでない場合は-1が返されます。自分でテストしていないので、調整が必要な場合があります。
希望します。
- 1. Cのセットビットの位置を取得
- 2. Facebook API最終イベントを取得する
- 3. PHPQueryで要素を最終的に取得するには?
- 4. ファイルシステムで最終更新日時を取得するには?
- 5. ファイルのリストの最終リビジョンを取得
- 6. 現在のアクティブユーザの最終レコードを取得する方法は?
- 7. クリック時の最終値を取得
- 8. URLの最終更新日を取得
- 9. ファイルの最終アクセス時間を取得
- 10. SharePoint:ユーザーの最終ログアウトまたは最終セッションの終了日時を取得する方法
- 11. BitArray
- 12. LibGit2Sharpリモートリポジトリの最終バージョンの取得
- 13. SQL PHP最終IDを取得
- 14. Django:最終訪問日を取得
- 15. 最終的なリダイレクトURLを取得
- 16. 最終更新レコードの取得
- 17. 最終ログイン時間の取得
- 18. 特定の要件を持つデータベーステーブルの最終行を取得するには?
- 19. 最終最初に挿入ゼロエントリMySQLの取得
- 20. ページの最終ページの値をPHPのファイル_get_contentsで取得する
- 21. Sequelize Promiseのチェーンの最終結果を取得する
- 22. データベース内のテーブルの最終更新時刻を取得する
- 23. linuxのファイルの最終更新時刻を取得する
- 24. ハイブのレコードから2番目の最終日を取得するには?
- 25. 私のウェブサイトで各URLの最終更新日を取得するには、C#
- 26. ストレージアカウント内の最新ファイルの最終更新日を取得
- 27. Javaでファイルの最終更新日を取得する
- 28. GitHub APIユーザーの最終ログインを取得する
- 29. Android - 最終リリースのAPK証明書を取得する
- 30. SharePointリスト(SPList)の最終更新日を取得する方法
使用 'Linq' =>' arrayInstance.Last() 'あなたの配列が短いので、もしそれが、整数型に容易になるだろう –
あなたはそれを十分に考慮するかもしれません。 – harold
Linqは高速ではありません。私は悲しい - "効果的"。 LINQはありません! –