Что такое эффективный (быстрый) способ получить последний бит бит в BitArray. (LINQ или простой обратный цикл не очень быстрый для больших растровых изображений. И мне нужно быстро) BitArray Я вижу следующий алгоритм: вернитесь через внутренние данные массива BitArray и используйте некоторый компилятор Intrinsic Like 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;
}
Решения отражения 50-100x быстрее для меня на большом BitArray
s (на очень маленьких будут появляться накладные расходы отражения). Это занимает около 0,2 мс на мегабайт на моей машине.
Главное, что if (b != 0)
проверяет сразу 32 бита. Внутренний цикл, который проверяет определенные биты, выполняется только один раз, когда найдено правильное слово.
Отредактировано: небезопасный код удален, потому что я понял, что он ничего не получил, он избегает проверки границы массива, и поскольку код настолько быстр, это уже не так важно. Для записи, небезопасное решение (~ 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 «эффективный» субъективен. Вы должны быть более информативными, если хотите получить более конкретные ответы. В любом случае вам придется пройти через битстрай, что и делает Linq.В противном случае, если вы хотите использовать битовые операторы для этого, вам нужно использовать более примитивный тип, чем «BitArray». – juharr
Я не верю, что есть что-то, что можно сделать, кроме повторения от последнего до первого бита, и спросить каждого, если он установлен. Это может быть сделано с помощью чего-то вроде:
BitArray bits = ...;
int lastSet = Enumerable.Range(1, bits.Length)
.Select(i => bits.Length - i)
.Where(i => bits[i])
.DefaultIfEmpty(-1)
.First();
Это должно вернуть последний бит, или -1, если таковой нет. Не проверял сам, так что это может потребовать некоторой корректировки.
Надеюсь, это поможет.
Linq не работает быстро. Я грустный - «эффективный». Нет LINQ! –
Вы можете заменить использование LINQ простым 'for' с конца BitArray на передний план. – Fede
Теперь я вижу, что вы отредактировали вопрос, чтобы спросить конкретно об отсутствии linq и не переходить с конца на передний план. Я не думаю, что BitArray будет соответствовать вашим потребностям. Я бы пошел с пользовательской реализацией BitArray, которая позволит вам получить доступ к внутреннему массиву int/long, чтобы вы могли спросить, равно ли 32/64 бит за раз 0. – Fede
- 1. Как получить байт * для бит в BitArray?
- 2. Как получить последний n бит бит-op?
- 3. BitArray - бит сдвига
- 4. Заменить бит в BitArray C#
- 5. BitArray возвращает бит неправильным способом?
- 6. Как я могу получить смещения всех заданных бит в bitarray?
- 7. Удалить последний бит байта
- 8. Индексирование BitArray, где бит определяется общим Enum
- 9. C - BitArray - установить один бит uint64_t
- 10. Инвертировать последний бит
- 11. Преобразование бит-бит в один бит
- 12. Операция бит: получить один бит в числе
- 13. добавить и удалить последний бит
- 14. Строка бит в Юникод
- 15. Бит бит в рубине
- 16. Бит-бит C/C++ или бит-вектор
- 17. Ядро бит решетки Eratosthenes
- 18. Как запускать бит Бит-компьютер
- 19. @@ ОПЦИИ бит-бит против DISABLE_DEF_CNST_CHK
- 20. Бит-манипуляция с ByteArray
- 21. C бит поле/массив
- 22. 16 бит бит глубина
- 23. 24-бит-1 бит-бит-преобразование
- 24. двоичный файл бит бит
- 25. Бит стоимость смещения бит
- 26. Базисная длина бит бит массив
- 27. Бит Маскировка бит регистра
- 28. Как конвертировать 8 бит в 16 бит?
- 29. Побитовая проверка бит бит
- 30. бит бит И
использование 'Linq' =>' arrayInstance.Last() ' –
Было бы проще в интегральном типе, так что если ваш массив короток достаточно, чтобы вы могли подумать об этом. – harold
Linq не быстрый. Я грустный - «эффективный». Нет LINQ! –