Quantcast
Viewing all articles
Browse latest Browse all 223

Answer by Peter - Reinstate Monica for C program return 1 if x > 0, 0 if x = 0, or -1 x < 0

It is well possible that I missed the point by assuming you can branch and simply return -1 etc. in my other answer.

Here is a solution (in C++, but that doesn't matter) which constructs a value of 1, 0 or -1 in a single expression, using only bit operators. I made it readable by heavily using defines but you could write it out as well. (The defines assume a variable n which should really be its own macro parameter, but it's actually clearer this way, if we want to use that word here.)

The idea is to combine "bit spreading" and "bit conflating": The left subexpression "spreads" the sign bit over all bits in the number, resulting in either 0 or -1, depending on the sign. (I'm talking in signed terms although the parameter is unsigned; C and C++ convert automatically, preserving the bit pattern. I use unsigned because the shift operations are well defined there.)

The right subexpression "conflates" all bits into the least significant bit, resulting in either 0 or 1 depending on whether any bit was set (i.e., whether the number was not zero).

  • ORing the two will not change the left -1 in case the number was negative.
  • It will OR two zeroes if the number itself is zero, resulting in a zero result as desired.
  • It will OR a zero and a 1 in case the number was true positive.
#include <iostream>#include <climits>using namespace std;/// Get the Nth bit in n (lsb for N==0)#define BIT(N) (n & (1 << N)) /// 1 if the Nth bit is set, else 0.#define BITTOONE(N) (BIT(N) >> N)/// OR the Nth bit, normalized to 1, with bit 0. /// If we do this for all bits, the expression is 1 if any bit was set.#define BITTOONE_ORED(N) (BITTOONE(N) | BIT(0))/// Shift the sign bit N places /// (note that N is not the bit index but the shift distance)./// We are not allowed to subtract, but luckily 31 has /// no gap in its bits so that a subtraction amounts to simply /// deleting the subtrahend bits in 31.#define SIGN_TO_N(N) (BIT(31) >> (31 & ~N))/// Tricky: Do something for all bits from 0..31 and do something with the bit operation results./// A simple example is the DO_FOR_ALL_BITS(BIT, |) which simply re-ORs /// all the bits, resulting in the original number./// Basically an unrolled loop, since we cannot use decrement etc.#define DO_FOR_ALL_BITS(op_with_bit, op_between) \   (           (op_with_bit(0))  op_between (op_with_bit(1))  op_between (op_with_bit(2))  op_between (op_with_bit(3)) \    op_between (op_with_bit(4))  op_between (op_with_bit(5))  op_between (op_with_bit(6))  op_between (op_with_bit(7))  \    op_between (op_with_bit(8))  op_between (op_with_bit(9))  op_between (op_with_bit(10)) op_between (op_with_bit(11))  \    op_between (op_with_bit(12)) op_between (op_with_bit(13)) op_between (op_with_bit(14)) op_between (op_with_bit(15))  \    op_between (op_with_bit(16)) op_between (op_with_bit(17)) op_between (op_with_bit(18)) op_between (op_with_bit(19))  \    op_between (op_with_bit(20)) op_between (op_with_bit(21)) op_between (op_with_bit(22)) op_between (op_with_bit(23))  \    op_between (op_with_bit(24)) op_between (op_with_bit(25)) op_between (op_with_bit(26)) op_between (op_with_bit(27))  \    op_between (op_with_bit(28)) op_between (op_with_bit(29)) op_between (op_with_bit(30)) op_between (op_with_bit(31))) int is_neg_zero_or_pos2(unsigned int n){    return DO_FOR_ALL_BITS(SIGN_TO_N, | ) | DO_FOR_ALL_BITS(BITTOONE_ORED, | );}void testBitopsFunc(unsigned int n){    int res = is_neg_zero_or_pos2(n);    // n is unsigned. negative values of the argument     // are represented as values > INT_MAX since the sign bit is set.    int expected = n > INT_MAX ? -1 : n > 0 ? 1 : 0;    cout << "Expected:" << expected << ", returned: " << res << '\n';    if (expected != res)    {        cout << "######## ERROR ########\n";    }}int main(){    testBitopsFunc(0) ;    testBitopsFunc(1) ;    testBitopsFunc(2);    testBitopsFunc(74326532);    testBitopsFunc(INT_MAX);    testBitopsFunc(-1);    testBitopsFunc(-2);    testBitopsFunc(-832547632);    testBitopsFunc(INT_MIN);}

A godbolt session is here.


Viewing all articles
Browse latest Browse all 223

Trending Articles