mam zmierzyć osiągów wszystkich odpowiedzi.
Zwycięzca nie ma tutaj klasycznego podejścia do sekwencji De Bruijn.
private const ulong DeBruijnSequence = 0x37E84A99DAE458F;
private static readonly int[] MultiplyDeBruijnBitPosition =
{
0, 1, 17, 2, 18, 50, 3, 57,
47, 19, 22, 51, 29, 4, 33, 58,
15, 48, 20, 27, 25, 23, 52, 41,
54, 30, 38, 5, 43, 34, 59, 8,
63, 16, 49, 56, 46, 21, 28, 32,
14, 26, 24, 40, 53, 37, 42, 7,
62, 55, 45, 31, 13, 39, 36, 6,
61, 44, 12, 35, 60, 11, 10, 9,
};
/// <summary>
/// Search the mask data from least significant bit (LSB) to the most significant bit (MSB) for a set bit (1)
/// using De Bruijn sequence approach. Warning: Will return zero for b = 0.
/// </summary>
/// <param name="b">Target number.</param>
/// <returns>Zero-based position of LSB (from right to left).</returns>
private static int BitScanForward(ulong b)
{
Debug.Assert(b > 0, "Target number should not be zero");
return MultiplyDeBruijnBitPosition[((ulong)((long)b & -(long)b) * DeBruijnSequence) >> 58];
}
Najszybszym sposobem jest wstrzyknięcie Bit Skanuj do przodu (BSF) Bit instrukcja do montażu po kompilator JIT zamiast BitScanForward ciała, ale to wymaga dużo więcej wysiłku.
Czy możesz wskazać coś, co definiuje "ostatnią znaczącą pozycję bitową", jak masz na myśli? Czy odnosisz się do pozycji "2" (obok ostatniego bitu), ponieważ ma ona wartość 1, ale dla 10011 ostatni znaczący bit będzie wynosił 1, a dla 10100 będzie to 4? –
Prawdopodobnie pomoże koncepcja binarnego wyszukiwania z modulo. – Ian
To rozwiązanie jest napisane w C++, ale powinno być możliwe dostosowanie do C# i jest tylko kilkoma operacjami: http://stackoverflow.com/a/757266/116614. Zobacz także http://stackoverflow.com/q/31374628/116614 – mellamokb