Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if multiple variable values are either all positive or negative

Tags:

c++

c

Is there a good and fast way in C/C++ to test if multiple variables contains either all positive or all negative values?

Say there a 5 variables to test:

Variant 1

int test(int a[5]) {
    if (a[0] < 0 && a[1] < 0 && a[2] < 0 && a[3] < 0 && a[4] < 0) {
        return -1;
    } else if (a[0] > 0 && a[1] > 0 && a[2] > 0 && a[3] > 0 && a[4] > 0) {
        return 1;
    } else {
        return 0;
    }
}

Variant 2

int test(int a[5]) {
    unsigned int mask = 0;
    mask |= (a[0] >> numeric_limits<int>::digits) << 1;
    mask |= (a[1] >> numeric_limits<int>::digits) << 2;
    mask |= (a[2] >> numeric_limits<int>::digits) << 3;
    mask |= (a[3] >> numeric_limits<int>::digits) << 4;
    mask |= (a[4] >> numeric_limits<int>::digits) << 5;
    if (mask == 0) {
        return 1;
    } else if (mask == (1 << 5) - 1) {
        return -1;
    } else {
        return 0;
    }
}

Variant 2a

int test(int a[5]) {
    unsigned int mask = 0;
    for (int i = 0; i < 5; i++) {
        mask <<= 1;
        mask |= a[i] >> numeric_limits<int>::digits;
    }
    if (mask == 0) {
        return 1;
    } else if (mask == (1 << 5) - 1) {
        return -1;
    } else {
        return 0;
    }
}

What Version should I prefer? Is there any adavantage using variant 2/2a over 1? Or is there a better/faster/cleaner way?

like image 372
bkausbk Avatar asked Dec 03 '22 02:12

bkausbk


2 Answers

I think your question and what you're looking for don't agree. You asked how to detect if they're signed or unsigned, but it looks like you mean how to test if they're positive or negative.

A quick test for all negative:

if ((a[0]&a[1]&a[2]&a[3]&a[4])<0)

and all non-negative (>=0):

if ((a[0]|a[1]|a[2]|a[3]|a[4])>=0)

I can't think of a good way to test that they're all strictly positive (not zero) right off, but there should be one.

Note that these tests are correct and portable for twos complement systems (anything in the real world you would care about), but they're slightly wrong for ones complement or sign-magnitude. They might can be fixed if you really care.

like image 94
R.. GitHub STOP HELPING ICE Avatar answered Jan 25 '23 23:01

R.. GitHub STOP HELPING ICE


I guess you mean negative/positive, (un)signed means whether a sign exists at all. This one works for any iterable (this assumes you count 0 as positive):

template <class T>
bool allpos(const T start, const T end) {
    T it;
    for (it = start; it != end; it++) {
        if (*it < 0) return false;
    }

    return true;
}

// usage
int a[5] = {-5, 3, 1, 0, 4};
bool ispos = allpos(a, a + 5);

Note: This is a good and fast way

This may not be the absolutely extremely superduperfastest way to do it, but it certainly is readable and really fast. Optimizing this is just not worth it.

like image 25
orlp Avatar answered Jan 25 '23 23:01

orlp