compare a large number of variables

Discussion in 'C Programming' started by Einar, Aug 16, 2005.

  1. Einar

    Einar Guest

    Hi,

    I wonder if there is a nice bit twiddling hack to compare a large
    number of variables?

    If you first store them in an array, you can do:

    for (i = 0; i < n; i++) {
    if (array != value) {
    /* array differs from value, do something*/
    }
    }

    but I dont have the variables in an array, and would like to figure out
    a nice oneliner.

    best regards.
    E.
     
    Einar, Aug 16, 2005
    #1
    1. Advertising

  2. Einar wrote:
    > Hi,
    >
    > I wonder if there is a nice bit twiddling hack to compare a large
    > number of variables?
    >
    > If you first store them in an array, you can do:
    >
    > for (i = 0; i < n; i++) {
    > if (array != value) {
    > /* array differs from value, do something*/
    > }
    > }
    >
    > but I dont have the variables in an array, and would like to figure out
    > a nice oneliner.
    >


    N nice one liners:

    if (var1 != value) { /* do smth */ }
    if (var2 != value) { /* do smth */ }
    ....
    if (varN != value) { /* do smth */ }


    P.Krumins
     
    Peteris Krumins, Aug 16, 2005
    #2
    1. Advertising

  3. Einar

    Eric Sosman Guest

    Einar wrote:
    > Hi,
    >
    > I wonder if there is a nice bit twiddling hack to compare a large
    > number of variables?
    >
    > If you first store them in an array, you can do:
    >
    > for (i = 0; i < n; i++) {
    > if (array != value) {
    > /* array differs from value, do something*/
    > }
    > }
    >
    > but I dont have the variables in an array, and would like to figure out
    > a nice oneliner.


    I'm not sure what you're looking for, but it might
    be one of

    if (a != value || b != value || ... || z != value) {
    /* at least one of a,b,...,z differs from
    * value, do something */
    }

    or

    if (a != value && b != value && ... &&& z != value) {
    /* all of a,b,...,z differ from value, do
    * something */
    }

    or

    if (a != value) {
    /* a differs from value, do something */
    }
    if (b != value) {
    /* b differs from value, do something */
    }
    ...
    if (z != value) {
    /* z differs from value, do something */
    }

    or as above but with `else' before all but the first `if'

    or

    int *ptr[] = { &a, &b, ..., &z };
    for (i = 0; i < n; ++i) {
    if (*ptr != value) {
    /* The i'th of a,b,...,z differs from
    * value, do something */
    }
    }

    If none of these is what you're trying to do, you'll
    have to explain your intent more clearly.

    --
     
    Eric Sosman, Aug 16, 2005
    #3
  4. Einar wrote:
    > Hi,
    >
    > I wonder if there is a nice bit twiddling hack to compare a large
    > number of variables?
    >
    > If you first store them in an array, you can do:
    >
    > for (i = 0; i < n; i++) {
    > if (array != value) {
    > /* array differs from value, do something*/
    > }
    > }
    >
    > but I dont have the variables in an array, and would like to figure out
    > a nice oneliner.
    >


    N nice one liners:

    if (var1 != value) { /* do smth */ }
    if (var2 != value) { /* do smth */ }
    ....
    if (varN != value) { /* do smth */ }


    P.Krumins
     
    Peteris Krumins, Aug 16, 2005
    #4
  5. "Einar" <> writes:
    > I wonder if there is a nice bit twiddling hack to compare a large
    > number of variables?
    >
    > If you first store them in an array, you can do:
    >
    > for (i = 0; i < n; i++) {
    > if (array != value) {
    > /* array differs from value, do something*/
    > }
    > }
    >
    > but I dont have the variables in an array, and would like to figure out
    > a nice oneliner.


    Perhaps they should be in an array.

    If that's not an option, and you're going to be doing this a lot, you
    might consider setting up an array of pointers to the variables and
    looping over that.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 16, 2005
    #5
  6. Einar

    Jack Klein Guest

    On 16 Aug 2005 08:12:35 -0700, "Einar" <> wrote in
    comp.lang.c:

    > Hi,
    >
    > I wonder if there is a nice bit twiddling hack to compare a large
    > number of variables?
    >
    > If you first store them in an array, you can do:
    >
    > for (i = 0; i < n; i++) {
    > if (array != value) {
    > /* array differs from value, do something*/
    > }
    > }
    >
    > but I dont have the variables in an array, and would like to figure out
    > a nice oneliner.
    >
    > best regards.
    > E.


    Here is a "trick" that I do not really recommend as best practice, but
    I have used in small microcontrollers for embedded systems with severe
    memory constraints.

    Assuming you have a header that contains the following:

    my_vars.h

    extern int val_a;
    extern int val_b;
    /* ... */
    extern int val_y;
    extern int val_z;

    ....and of course you have a source file:

    my_vars.c

    int val_a;
    int val_b;
    /* ... */
    int val_y;
    int val_z;

    ....then you could change my_vars.h to:

    extern int sneaky_array[];
    #define val_a sneaky_array[0]
    #define val_b sneaky_array[1]
    /* ... */
    #define val_y sneaky_array[24]
    #define val_z sneaky_array[25]

    ....and change my_vars.c:

    int sneaky_array[2];

    ....then you can write new code that can loop through the values as an
    array, whereas older source code that refers to individual elements by
    name will still compile and work with the new my_vars.h header.

    But I really, really don't recommend this except for exceptional
    circumstances.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Aug 17, 2005
    #6
  7. Einar

    Einar Guest

    Hello Eric,

    Yes, your suggestions work perfectly, but I was mor looking for a nice
    bit operator to operate on all my variables and then to compare it with
    the value. something like (a|b|c|d...z) != value (this wont work
    however... ). This is just to get rid of a for-loop or lots of
    if-statements, so it is nothing necesary, I'm just convinced that it is
    possible to solve in another way, and I can't forget about it....
    Ahhhrg.

    best regards.
    E.
     
    Einar, Aug 17, 2005
    #7
  8. Einar

    AM Guest

    Hi,

    This might help you...

    /* file.e */
    USE(a)
    USE(b)
    USE(c)

    /* file.c */
    /* Inside your function */
    #define USE(var) do { \
    if ( ##var != value) \
    { \
    /* your stuff */ \
    } \
    while(0);
    #include "file.e"

    you can compile the code with -E option (gcc) and see the expanded code
    as follows-

    do { if (a > value ) { } while (0);
    do { if (b > value ) { } while (0);
    do { if (c > value ) { } while (0);

    Regards,
    -A M
     
    AM, Aug 17, 2005
    #8
  9. Einar

    Netocrat Guest

    On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:

    > Hello Eric,
    >
    > Yes, your suggestions work perfectly, but I was mor looking for a nice
    > bit operator to operate on all my variables and then to compare it with
    > the value. something like (a|b|c|d...z) != value (this wont work
    > however... ). This is just to get rid of a for-loop or lots of
    > if-statements, so it is nothing necesary, I'm just convinced that it is
    > possible to solve in another way, and I can't forget about it....
    > Ahhhrg.


    How about (off the top of my head and untested):

    if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
    /* one or more of a,b,c,d...z is not equal to value */

    I don't think that would generally be as efficient as using multiple
    comparisons against value because in that case the first mismatch will
    prevent the rest from being evaluated. You never know though - on some
    hardware it might be; or the compiler might rewrite it for you.

    Another alternative (also untested):

    if ( ((a|b|c|d...z)&a&b&c&d...z) != value )
    /* one or more of a,b,c,d...z is not equal to value */

    --
    http://members.dodo.com.au/~netocrat
     
    Netocrat, Aug 17, 2005
    #9
  10. Einar

    Guest

    Rerwite code to have them all grouped in a user defined type and then
    use memcmp().
     
    , Aug 17, 2005
    #10
  11. Einar

    Flash Gordon Guest

    wrote:
    > Rerwite code to have them all grouped in a user defined type and then
    > use memcmp().


    All what? Learn to quote. The google interface may by broken but it is
    possible, and if you had read this (or almost any other group) you would
    have seen that it is the done thing.

    Search this group for broken google interface and you will see *lots* of
    complaints, explanations of the problem, and instructions on how to get
    Google to do the right thing.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Aug 17, 2005
    #11
  12. AM wrote:

    > #define USE(var) do { \
    > if ( ##var != value) \
    > { \
    > /* your stuff */ \
    > } \
    > while(0);

    ....
    > you can compile the code with -E option (gcc) and see the expanded code
    > as follows-
    >
    > do { if (a > value ) { } while (0);
    > do { if (b > value ) { } while (0);
    > do { if (c > value ) { } while (0);


    That's right. You can see the expanded code. You can't compile it
    though. (Missing right brace.)

    Peter
     
    Peter Pichler, Aug 17, 2005
    #12
  13. In article <>, Netocrat <> writes:
    > On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
    >
    > > Yes, your suggestions work perfectly, but I was mor looking for a nice
    > > bit operator to operate on all my variables and then to compare it with
    > > the value. something like (a|b|c|d...z) != value (this wont work
    > > however... ).

    >
    > How about (off the top of my head and untested):
    >
    > if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
    > /* one or more of a,b,c,d...z is not equal to value */


    Or the similarly silly:

    if (a^value|b^value|c^value|...|z^value)
    /* one or more of a,b,c,...,z is not equal to value */

    (Untested, but I think that's right.) Or similarly:

    if (a^b|b^c|c^d|...|y^z|z^value)

    All assuming that we're working with values that aren't going to
    produce trap representations, or with unsigned types.

    Of course this is just a bitwise version of (in the second case):

    if (a!=b || b!=c || ... || z!=value)

    except that the logical version can short-circuit, so fewer
    operations are performed. (Though it's conceivable that on some
    systems it'd be faster to perform all the bitwise operations than
    to do the comparing and branching required to implement short-
    circuiting.)

    > I don't think that would generally be as efficient as using multiple
    > comparisons against value because in that case the first mismatch will
    > prevent the rest from being evaluated.


    More important, it's lousy code, and performance is rarely as
    important as maintainability. And if performance *is* crucial in
    this case, then it's probably time to redesign - it's unlikely that
    keeping a lot of independent variables and testing them all against a
    single value is actually the best way to accomplish whatever it is
    that the problem requires.

    That said, in some code I might find it defensible to write this as
    a multiline controlling expression in an if statement (using the
    logical operators, not the bitwise ones), as long as it was clear.


    --
    Michael Wojcik

    Ten or ten thousand, does it much signify, Helen, how we
    date fantasmal events, London or Troy? -- Basil Bunting
     
    Michael Wojcik, Aug 18, 2005
    #13
  14. Einar

    Netocrat Guest

    On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
    > In article <>, Netocrat
    > <> writes:
    >> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
    >>
    >> > Yes, your suggestions work perfectly, but I was mor looking for a
    >> > nice bit operator to operate on all my variables and then to compare
    >> > it with the value. something like (a|b|c|d...z) != value (this wont
    >> > work however... ).

    >>
    >> How about (off the top of my head and untested):
    >>
    >> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
    >> /* one or more of a,b,c,d...z is not equal to value */

    >
    > Or the similarly silly:
    >
    > if (a^value|b^value|c^value|...|z^value)
    > /* one or more of a,b,c,...,z is not equal to value */


    No that doesn't work. In the case of one variable with a==1, value==1
    then a^value is false. I can't see a way to rearrange it using bitwise
    or/and to work.

    This really calls for a multi-way equality comparison:

    if ( ! (a == b == c == d == ... == z == value) )

    Obviously the semantics are wrong the way the equality operator is
    currently defined, but I've sometimes wanted to use an expression like
    this.

    > (Untested, but I think that's right.) Or similarly:
    >
    > if (a^b|b^c|c^d|...|y^z|z^value)


    Same problem as above.

    > All assuming that we're working with values that aren't going to produce
    > trap representations, or with unsigned types.


    Right, these bitwise operations on signed integers are not portable.

    > Of course this is just a bitwise version of (in the second case):
    >
    > if (a!=b || b!=c || ... || z!=value)


    Except that the logical or can't be replaced with a bitwise or.

    [...]
    >> I don't think that would generally be as efficient as using multiple
    >> comparisons against value because in that case the first mismatch will
    >> prevent the rest from being evaluated.

    >
    > More important, it's lousy code,


    Its purpose is not immediately clear and it depends on unsigned integers.
    Both issues can be dealt with by appropriate commenting. More typical
    expressions would avoid the need for commenting but I don't think that
    makes it "lousy" code - it's perfectly serviceable, just a little atypical
    and obscure.

    > and performance is rarely as
    > important as maintainability. And if performance *is* crucial in this
    > case, then it's probably time to redesign - it's unlikely that keeping a
    > lot of independent variables and testing them all against a single value
    > is actually the best way to accomplish whatever it is that the problem
    > requires.


    That's quite a sweeping claim (as to likelihood of needing a multi-way
    test) and I haven't given much thought to its merits but I'm curious by
    what reasoning you make it.

    [...]

    --
    http://members.dodo.com.au/~netocrat
     
    Netocrat, Aug 18, 2005
    #14
  15. Einar

    pete Guest

    Netocrat wrote:
    >
    > On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:


    > > if (a!=b || b!=c || ... || z!=value)

    >
    > Except that the logical or can't be replaced with a bitwise or.


    Logical or can be replaced with a bitwise or,
    when the arguments are all boolean (either 1 or 0),
    and it doesn't matter that there's no short circuiting.

    (0 || 0 || 1 || 0) == (0 | 0 | 1 | 0)

    --
    pete
     
    pete, Aug 18, 2005
    #15
  16. Einar

    Netocrat Guest

    On Thu, 18 Aug 2005 19:03:32 +0000, pete wrote:

    > Netocrat wrote:
    >>
    >> On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:

    >
    >> > if (a!=b || b!=c || ... || z!=value)

    >>
    >> Except that the logical or can't be replaced with a bitwise or.

    >
    > Logical or can be replaced with a bitwise or,
    > when the arguments are all boolean (either 1 or 0),
    > and it doesn't matter that there's no short circuiting.
    >
    > (0 || 0 || 1 || 0) == (0 | 0 | 1 | 0)


    The statement quoted top of post was being compared with:

    if (a^b|b^c|c^d|...|y^z|z^value)

    They are equivalent statements only when each variable represents a single
    bit. For a single bit, a ^ b is equivalent to a != b and as you pointed
    out, a | b is equivalent to a || b. But for variables comprised of
    multiple bits, the equivalence no longer holds.

    So yes, I agree with you, but it doesn't apply in this case because a, b,
    etc aren't boolean variables.

    --
    http://members.dodo.com.au/~netocrat
     
    Netocrat, Aug 18, 2005
    #16
  17. Einar

    Netocrat Guest

    On Fri, 19 Aug 2005 05:17:27 +1000, Netocrat wrote:
    > On Thu, 18 Aug 2005 19:03:32 +0000, pete wrote:
    >> Netocrat wrote:
    >>> On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:

    >>
    >>> > if (a!=b || b!=c || ... || z!=value)
    >>>
    >>> Except that the logical or can't be replaced with a bitwise or.

    >>
    >> Logical or can be replaced with a bitwise or,
    >> when the arguments are all boolean (either 1 or 0),
    >> and it doesn't matter that there's no short circuiting.
    >>
    >> (0 || 0 || 1 || 0) == (0 | 0 | 1 | 0)

    >
    > The statement quoted top of post was being compared with:
    >
    > if (a^b|b^c|c^d|...|y^z|z^value)
    >
    > They are equivalent statements only when each variable represents a single
    > bit. For a single bit, a ^ b is equivalent to a != b and as you pointed
    > out, a | b is equivalent to a || b. But for variables comprised of
    > multiple bits, the equivalence no longer holds.
    >
    > So yes, I agree with you, but it doesn't apply in this case because a, b,
    > etc aren't boolean variables.


    OK I've worded the concluding sentence inaccurately. Try this instead:
    So your comment is valid and my original analysis should have rejected
    the replacement of != with ^ rather than | with ||.

    --
    http://members.dodo.com.au/~netocrat
     
    Netocrat, Aug 18, 2005
    #17
  18. Einar

    Netocrat Guest

    On Thu, 18 Aug 2005 13:03:34 -0700, Tim Rentsch wrote:
    > Netocrat <> writes:
    >> On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
    >> > In article <>, Netocrat
    >> > <> writes:
    >> >> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
    >> >>
    >> >> > Yes, your suggestions work perfectly, but I was mor looking for a
    >> >> > nice bit operator to operate on all my variables and then to compare
    >> >> > it with the value. something like (a|b|c|d...z) != value (this wont
    >> >> > work however... ).
    >> >>
    >> >> How about (off the top of my head and untested):
    >> >>
    >> >> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
    >> >> /* one or more of a,b,c,d...z is not equal to value */
    >> >
    >> > Or the similarly silly:
    >> >
    >> > if (a^value|b^value|c^value|...|z^value)
    >> > /* one or more of a,b,c,...,z is not equal to value */

    >>
    >> No that doesn't work. In the case of one variable with a==1, value==1
    >> then a^value is false.

    >
    > Please read the comment after the 'if' line.


    It's identical to my original comment except for the addition of a couple
    of commas. Please be more specific.

    --
    http://members.dodo.com.au/~netocrat
     
    Netocrat, Aug 18, 2005
    #18
  19. Einar

    Mark Guest

    "Netocrat" <> wrote in message
    news:p...
    > On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
    >> In article <>, Netocrat
    >> <> writes:
    >>> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
    >>>
    >>> > Yes, your suggestions work perfectly, but I was mor looking for a
    >>> > nice bit operator to operate on all my variables and then to compare
    >>> > it with the value. something like (a|b|c|d...z) != value (this wont
    >>> > work however... ).
    >>>
    >>> How about (off the top of my head and untested):
    >>>
    >>> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
    >>> /* one or more of a,b,c,d...z is not equal to value */

    >>
    >> Or the similarly silly:
    >>
    >> if (a^value|b^value|c^value|...|z^value)
    >> /* one or more of a,b,c,...,z is not equal to value */

    >
    > No that doesn't work. In the case of one variable with a==1, value==1
    > then a^value is false. I can't see a way to rearrange it using bitwise
    > or/and to work.


    Albeit ugly, this should work:

    if(a-b|b-c|c-d|d-e /* ... */)
    puts("mismatched");
    else
    puts("pick one... they're all the same");
     
    Mark, Aug 18, 2005
    #19
  20. Einar

    Tim Rentsch Guest

    Netocrat <> writes:

    > On Thu, 18 Aug 2005 17:11:25 +0000, Michael Wojcik wrote:
    > > In article <>, Netocrat
    > > <> writes:
    > >> On Tue, 16 Aug 2005 23:55:15 -0700, Einar wrote:
    > >>
    > >> > Yes, your suggestions work perfectly, but I was mor looking for a
    > >> > nice bit operator to operate on all my variables and then to compare
    > >> > it with the value. something like (a|b|c|d...z) != value (this wont
    > >> > work however... ).
    > >>
    > >> How about (off the top of my head and untested):
    > >>
    > >> if ( !( ((a|b|c|d...z) == value) && ((a&b&c&d...z) == value) ) )
    > >> /* one or more of a,b,c,d...z is not equal to value */

    > >
    > > Or the similarly silly:
    > >
    > > if (a^value|b^value|c^value|...|z^value)
    > > /* one or more of a,b,c,...,z is not equal to value */

    >
    > No that doesn't work. In the case of one variable with a==1, value==1
    > then a^value is false.


    Please read the comment after the 'if' line.
     
    Tim Rentsch, Aug 18, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Noozer
    Replies:
    2
    Views:
    4,134
    Noozer
    Sep 19, 2004
  2. FC
    Replies:
    3
    Views:
    419
    Ioannis Vranos
    Mar 4, 2005
  3. www
    Replies:
    3
    Views:
    1,609
    Roedy Green
    Jun 29, 2007
  4. Replies:
    9
    Views:
    997
  5. Joe Young

    Compare two extremely large lists?

    Joe Young, Jan 17, 2011, in forum: Perl Misc
    Replies:
    7
    Views:
    156
    Joe Young
    Jan 18, 2011
Loading...

Share This Page