2011-02-23 3 views
3

Есть все короче и лучше выглядящий альтернативаБитовые операции в C#

(b == 0) ? 0 : 1; 

в терминах поразрядных операций?

Кроме того, чтобы получить правильный знак (-1, 0 или 1) данный целый a я в настоящее время с помощью

(a > 0) ? 1 : (a >> 32); 

Есть ли более короткий (но не медленнее) путь?

+0

Вы должны перейти на 31, а не 32. Если вы считаете, что измерить его, чтобы быть быстрее, чем Math.Sign(), а затем поменять местами испытания. –

ответ

6

Лично я бы придерживался первого варианта для вашей опции «равный нулю или нет».

Для знака целого числа я использовал бы Math.Sign и предполагал, что компилятор JIT собирается встроить его - тестирование этого предположения с помощью тестов, если это окажется потенциальным узким местом.

Подумайте о читаемости, прежде всего - ваш первый фрагмент кода ослепительно очевиден. Второе - нет. Я даже не убежден в том, что ваш второй фрагмент кода работает ... Я думал, что правые смены были эффективно замаскированы на нижние 5 бит, если это Int32 (int).

EDIT: Только что проверил, да и текущая вторая часть кода эквивалентна:

int y = x > 0 ? 1 : x; 

Сдвиг даже не в конечном итоге в скомпилированный код.

Возьмите это как предметный урок о заботе о микро-оптимизации, а не о читаемости. Гораздо проще сделать код если это легко понять. Если ваш код дает неправильный результат, мне все равно, как быстро он работает.

+1

Согласно моим тестам, 'Math.Sign' намного медленнее, чем код, который я использую. Но, опять же, я бы хотел получить ответы с точки зрения поразрядных операций, а не альтернатив, так как я учусь! В любом случае, спасибо. – Miguel

+1

@Miguel: Не могли бы вы опубликовать эти тесты? Существует огромное количество способов получить неправильный бенчмарк ... –

+0

Вы заметили, что 'Int32.MaxValue >> 32' возвращает 0? Это означает, что он не ограничивается первыми 5 битами, поскольку это 32-битное число. – Miguel

4

Микрооптимизации являются корнем всех злых. Вы жертвуете удобочитаемостью для наносекунды. Это плохая сделка

+3

Я просто изучаю ... – Miguel

+3

@Miguel: Действительно, обнимая тот факт, что микрооптимизации являются злыми, получится гораздо полезнее, чем научиться делать какой-то побитовый трюк, поверьте мне –

+2

@Miguel: +1 для смирения. :) –

1

с точки зрения побитовых операций ... Может любой, пожалуйста, укажите это мне? Кроме того, , чтобы получить правильный знак (-1, 0 или 1) данного целого числа а я в настоящее время с помощью

(a > 0) ? 1 : (a >> 32); 

Армен Tsirunyan и Джон Скит ответил на ваш технический вопрос, я собираюсь попытайтесь объяснить некоторые технические неправильные представления, которые, как вам кажется, есть.

Первая ошибка заключается в том, что если у вас есть 32-битное целое число со знаком и вы пытаетесь сдвинуть его на 32, вы попытаетесь посмотреть на 33-й бит, который в случае подписанной базовой 2-артемии будет битом переполнения ,

Вторая ошибка заключается в том, что у вас есть 32-разрядное двоичное двоичное значение. Последний бит будет либо одним, либо ноль. Существует только одно нулевое значение. Таким образом, ваше заявление о попытке выяснить, является ли знак (-1,0,1), явно указывает на то, что вы не понимаете этого факта. Если подписанный бит равен 1, число будет отрицательным, если оно равно нулю, оно будет положительным.Структуры, которые обрабатывают число по большей части в .NET Framework, не знают о дополнении 2 и дополнении 1. Это, конечно, не означает, что вы не можете расширить эту функциональность или просто преобразовать целое число со знаком в число дополнений 2 (действительно просто честно).

Я должен добавить, что есть только одно значение для нуля, когда у вас есть целое число со знаком. Я думаю, это была моя главная проблема с вашим заявлением «проверить знак», которое вы сделали, что показывает неправильное представление о двоичных числах.

http://en.wikipedia.org/wiki/Signed_magnitude#Sign-and-magnitude

Смежные вопросы