Знаковая проблема

Давно ничего не писал. А тут вдруг решил проблему, которая периодически занимала меня последний месяц. Речь про задачу про знаки из первой лабораторной работы курсеровского курса Hardware/Software Interface. Из-за этой задачи, я собственно и дропнул этот курс – не сумел решить с наскоку и расстроился.

Суть задачи в том, что используя только операции сложения, вычитания, умножения, битового сдвига влево и вправо, побитовых И, ИЛИ, НЕ, исключающего ИЛИ и оператора логического отрицания решить задачу нахождения знака 32-битного числа со знаком. На вход функции подаётся число, на выходе должны быть:

  • 1 – если число положительное
  • -1 – если число отрицательное
  • 0 – если число – это ноль

Использовать какие-либо операторы сравнения запрещено.

Задача решается элементарно благодаря оператору логического отрицания. Суть этого оператора в том, что он возвращает единицу, если ему на вход дали ноль и возвращает ноль, если на вход ему дали не ноль.

Фишка в том, что знак хранится в 31-ом бите и сам по себе выделяется очень просто. Засада на месяц состояла в том, чтобы отделить положительные числа от нуля – в обоих случаях в 31-ом бите сидит ноль. А решение состоит в том, чтобы умножить выделенный знак на двойное логическое отрицание исходного числа. Вот и весь фокус. Весьма тривиальный и простой, но непривычный для меня.

out = (1-2*((unsigned)in>>31))*!!in;

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>