Discussion:
Value of a comparision operation
(too old to reply)
Vladimir Grigoriev
2008-07-07 12:49:39 UTC
Permalink
In C (not C++) what is the result value of the expression according to the
standard

( a == b )

int 1 or any int value greater than 0 ?

Vladimir Grigoriev
Martin Nijhoff
2008-07-07 13:09:37 UTC
Permalink
Hi Vladimir,

The result of any comparison is a boolean, so either true (= 1) or false (=
0).

Martin
Vladimir Grigoriev
2008-07-07 13:22:14 UTC
Permalink
Post by Martin Nijhoff
Hi Vladimir,
The result of any comparison is a boolean, so either true (= 1) or false
(= 0).
Martin
However C has not the type boolean, it has type int for any comparison
operation, has not it?

Vladimir Grigoriev
Martin Nijhoff
2008-07-07 14:22:02 UTC
Permalink
C does have the type bool, which is not by definition an int.

Martin
Post by Vladimir Grigoriev
Post by Martin Nijhoff
Hi Vladimir,
The result of any comparison is a boolean, so either true (= 1) or false
(= 0).
Martin
However C has not the type boolean, it has type int for any comparison
operation, has not it?
Vladimir Grigoriev
Thomas Maeder [TeamB]
2008-07-07 15:35:14 UTC
Permalink
Post by Martin Nijhoff
C does have the type bool, which is not by definition an int.
True, but "only" since C99.
Chris Uzdavinis (TeamB)
2008-07-07 22:53:12 UTC
Permalink
Post by Thomas Maeder [TeamB]
Post by Martin Nijhoff
C does have the type bool, which is not by definition an int.
True, but "only" since C99.
It be also be worth mentioning that C99 is not the version of C on
which C++ is based.
--
Chris (TeamB);
Ebbe Kristensen
2008-07-07 13:39:53 UTC
Permalink
Post by Vladimir Grigoriev
In C (not C++) what is the result value of the expression according
to the standard
( a == b )
int 1 or any int value greater than 0 ?
In C, true is any value that is not 0. So there are no guarantees - as I
learned the hard way many years ago. The construct:

#define TRUE 1
#define FALSE 0

...

if( TRUE == <something> )
...

failed because <something> did not return a '1'. Changed it to:

if( <something> )
...

and it worked as expected.

BTW, why do want to know?

Ebbe
Vladimir Grigoriev
2008-07-07 14:04:49 UTC
Permalink
Post by Ebbe Kristensen
Post by Vladimir Grigoriev
In C (not C++) what is the result value of the expression according
to the standard
( a == b )
int 1 or any int value greater than 0 ?
In C, true is any value that is not 0. So there are no guarantees - as I
#define TRUE 1
#define FALSE 0
...
if( TRUE == <something> )
...
if( <something> )
...
and it worked as expected.
BTW, why do want to know?
Ebbe
So you want to say that the expression

x + ( a == b ) will be in fact undefined and may have any value?

Vladimir Grigorieb
Duane Hebert
2008-07-07 14:17:28 UTC
Permalink
Post by Ebbe Kristensen
Post by Vladimir Grigoriev
In C (not C++) what is the result value of the expression according
to the standard
( a == b )
int 1 or any int value greater than 0 ?
In C, true is any value that is not 0. So there are no guarantees - as I
#define TRUE 1
#define FALSE 0
...
if( TRUE == <something> )
I don't think the problem here is with the comparison operator.
I think it always returns 1 when true (in both C and C++)

I think the problem is in how it is used. true doesn't have to
be 1. You can see this with an uninitialized bool. It can be
any number if you treat it as an int. If you try to
compare it to 1 it can fail even if it's not false. Using the define
above, you're comparing it to 1. Maybe this is the issue?
Chris Uzdavinis (TeamB)
2008-07-07 22:52:03 UTC
Permalink
Post by Duane Hebert
I think the problem is in how it is used. true doesn't have to
be 1. You can see this with an uninitialized bool. It can be
any number if you treat it as an int. If you try to
compare it to 1 it can fail even if it's not false. Using the define
above, you're comparing it to 1. Maybe this is the issue?
One old "trick" to normalize true values to 1 is to double-negate it.

// flip to false then back to true to ensure true is 1
int x = !!get_value();

In C++ it's easier to just create a boolean out of it:

int x = bool(get_value());

... assuming you really have to store it in an integer--which isn't
necessarily a good idea in the first place.


At this point I feel compelled to mention that I truly hate code like
this:

if (x == true)
{
return true;
}
else
{
return false;
}

It drives me crazy, in fact. :) I much prefer


return x;

Same with gratituous ternary operators. However, in this case (using
a bool as an integer for numeric math) it is arguably taking advantage
of details that are not quite part of the problem domain (such as the
numeric values of true and false), and could be (rightly) argued to
make code a less readable.

Probably a helper variable is the best solution. A good optimizer
won't incur any penalty for doing so.

int const first_page_factor = (page == FIRST_PAGE) ? 1 : 0;
if ( ( number_of_lines + first_page_factor ) == LINES_PER_PAGE )
{
bla, bla,bla...
}
--
Chris (TeamB);
Ebbe Kristensen
2008-07-08 07:27:53 UTC
Permalink
Post by Vladimir Grigoriev
So you want to say that the expression
x + ( a == b ) will be in fact undefined and may have any value?
I'd say that construct is about as portable as the Empire State Building.

Yes, it may work as expected with your current version of Borland C++
Builder. But it is not guaranteed to work if you upgrade that compiler to a
newer version or with other compilers.

The safe way to achieve what you want is this:

x + (( a == b ) ? 1 : 0);

The enclosing set of parenthesises is nedeed because '+' has higher
precedence than '?:'

Ebbe
Alan Bellingham
2008-07-08 08:32:39 UTC
Permalink
Post by Ebbe Kristensen
Post by Vladimir Grigoriev
So you want to say that the expression
x + ( a == b ) will be in fact undefined and may have any value?
I'd say that construct is about as portable as the Empire State Building.
No, it's as portable as anything in C.

Any non-zero value will be treated as true if you use it in a
conditional. But the *result* from any comparison (==, >, etc.) must be
1.

So, there are three value types:

false: 0
true: 1
not-false: any other
Post by Ebbe Kristensen
Yes, it may work as expected with your current version of Borland C++
Builder. But it is not guaranteed to work if you upgrade that compiler to a
newer version or with other compilers.
Any such compiler would be so badly broken that huge amounts of existing
code would probably break. If you have to worry about that sort of
thing, then you are going to have to start worrying about whether 2+2
gives 4 or not.
Post by Ebbe Kristensen
x + (( a == b ) ? 1 : 0);
This has no code advantage, though it does document what's intended
better.

Alan Bellingham
--
Team Browns
<url:http://www.borland.com/newsgroups/> Borland newsgroup descriptions
<url:http://www.borland.com/newsgroups/netiquette.html> netiquette
Ebbe Kristensen
2008-07-08 13:30:31 UTC
Permalink
Post by Alan Bellingham
No, it's as portable as anything in C.
I will admit that I am colored by the fact that I "grew up" with versions of
C where this was not the case :-)

Although the construct "x + ( a == b )" will give Vladimir the expected
result, I still think that constructs that require your fellow developers to
look up in the Standard are at best doubious. It may be "smart" today but if
it is not readily understood by the poor fellow who has to maintain it a
year hence, it will probably trigger a rewrite of the code accompanied by a
few choice words :-)

Ebbe
Hendrik Schober
2008-07-08 14:03:39 UTC
Permalink
[...] I still think that constructs that require your fellow developers to
look up in the Standard are at best doubious. [...]
The problem is that this definition of what is dubious
not only depends on the code, but also on the fellows.
Of course, everyone agrees that, whatever they don't
know, shouldn't be used. Unfortunately this includes
those who barely know how to spell"C", let alone write
C++.
So there has to be some other criterion.
Ebbe
Schobi
Chris Uzdavinis (TeamB)
2008-07-08 12:43:50 UTC
Permalink
Post by Ebbe Kristensen
Post by Vladimir Grigoriev
So you want to say that the expression
x + ( a == b ) will be in fact undefined and may have any value?
I'd say that construct is about as portable as the Empire State Building.
Actually, as long as we are staying within the confines of C and C++,
and the types of a and b don't have an overloaded operator that
changes the meaning of "true", then you should be able to bet your
life on it working. For built-in numeric types, equality returns a
bool (or an int in C) with guaranteed numeric value of 1 for true, and
0 for false.
Post by Ebbe Kristensen
Yes, it may work as expected with your current version of Borland C++
Builder. But it is not guaranteed to work if you upgrade that compiler to a
newer version or with other compilers.
x + (( a == b ) ? 1 : 0);
The enclosing set of parenthesises is nedeed because '+' has higher
precedence than '?:'
Hm, I don't think I like the way that looks. If we're going to
introduce a user-provided conditional, I think a normal "if" would be
more readable, and could avoid a gratituous assignment. Instead of:


y = x + (( a == b ) ? 1 : 0);

Why not:

if (a == b)
y = x + 1;
else
y = x;

Or:

y = x;
if (a == b)
++y;

Still, the conciseness is very attractive to the original code, and
the decision is "is our team comfortable with this kind of code?" If
more than half say yes, then it's probably the way to go. If the team
has trouble reading it, they'll have trouble maintaining it.

y = x + (a==b);


One could always throw in a helper variable to help name what is going
on.

int const extra = (a==b);
y = x + extra;

Etc.
--
Chris (TeamB);
Vladimir Grigoriev
2008-07-08 13:06:14 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
One could always throw in a helper variable to help name what is going
on.
int const extra = (a==b);
y = x + extra;
However you will not define the extra constant for every pair of variables,
will you?
The more I read comments the more I yield to the original form of the
expression :)

y = x + ( a == b );

Vladimir Grigoriev
Chris Uzdavinis (TeamB)
2008-07-08 13:31:20 UTC
Permalink
Post by Vladimir Grigoriev
Post by Chris Uzdavinis (TeamB)
One could always throw in a helper variable to help name what is going
on.
int const extra = (a==b);
y = x + extra;
However you will not define the extra constant for every pair of variables,
will you?
The more I read comments the more I yield to the original form of the
expression :)
y = x + ( a == b );
No, I wont name every temporary. Only if they're odd constructs, such
as using a logical truth value as a number in a math expression.

I only added the variable for the sake of critics who say it's
unreadable without it. That's a judgement call, but I disagree that
it's unreadable. A little unconventional, but not unreadable. It
feels like it's cheating *a little* but it's the cleanest version I've
seen yet.
--
Chris (TeamB);
Chris Uzdavinis (TeamB)
2008-07-07 13:58:16 UTC
Permalink
Post by Vladimir Grigoriev
In C (not C++) what is the result value of the expression according to the
standard
( a == b )
int 1 or any int value greater than 0 ?
According to the C standard, the value is 1:

6.5.9 Equality operators
(para 3)
"The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence. Each of
the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. ...
--
Chris (TeamB);
Vladimir Grigoriev
2008-07-07 14:12:40 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Post by Vladimir Grigoriev
In C (not C++) what is the result value of the expression according to the
standard
( a == b )
int 1 or any int value greater than 0 ?
6.5.9 Equality operators
(para 3)
"The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence. Each of
the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. ...
--
Chris (TeamB);
Thanks, Chris
.
I wrote already what I wanted. I did not want to use ternary operator. My
code looks something as

if ( ( number_of_lines + ( page == FIRST_PAGE ) ) == LINES_PER_PAGE )
bla, bla,bla...

Vladimir Grigoriev
Martin Nijhoff
2008-07-07 14:17:09 UTC
Permalink
To be on the safe side, I would change this to:

if ( ( number_of_lines + ( page == FIRST_PAGE ? 1 : 0) ) == LINES_PER_PAGE )

Martin
Vladimir Grigoriev
2008-07-07 14:32:02 UTC
Permalink
Post by Martin Nijhoff
if ( ( number_of_lines + ( page == FIRST_PAGE ? 1 : 0) ) ==
LINES_PER_PAGE )
Martin
Initially I was going to write the same. However I thought that ( page ==
FIRST_PAGE ) is the same as
( page == FIRST_PAGE ? 1 : 0). Why should I second time say that 1 is 1? :)

Vladimir Grigoriev
Duane Hebert
2008-07-07 14:39:50 UTC
Permalink
Post by Vladimir Grigoriev
Post by Martin Nijhoff
if ( ( number_of_lines + ( page == FIRST_PAGE ? 1 : 0) ) ==
LINES_PER_PAGE )
Martin
Initially I was going to write the same. However I thought that ( page ==
FIRST_PAGE ) is the same as
( page == FIRST_PAGE ? 1 : 0). Why should I second time say that 1 is 1? :)
Why is it necessary to put this in one line instead of expressing it
more clearly (IMO)?
Vladimir Grigoriev
2008-07-07 14:50:25 UTC
Permalink
The original expression is different (no pages, no lines). And I found it
clear. IMO using ternary operator or splitting the expression in
subexpression in one if statement made code more complicated

Vladimir Grigoriev
Post by Duane Hebert
Post by Vladimir Grigoriev
Post by Martin Nijhoff
if ( ( number_of_lines + ( page == FIRST_PAGE ? 1 : 0) ) ==
LINES_PER_PAGE )
Martin
Initially I was going to write the same. However I thought that ( page
== FIRST_PAGE ) is the same as
( page == FIRST_PAGE ? 1 : 0). Why should I second time say that 1 is 1? :)
Why is it necessary to put this in one line instead of expressing it
more clearly (IMO)?
Duane Hebert
2008-07-07 15:03:19 UTC
Permalink
Post by Vladimir Grigoriev
The original expression is different (no pages, no lines). And I found it
clear. IMO using ternary operator or splitting the expression in
subexpression in one if statement made code more complicated
Ok. I just found that from the example, taking a "number of lines", adding
a 1 or 0
based on whether it's the first page and then comparing it to a define
called
LINES_PER_PAGE was not so clear.

I agree with you regarding ternary operator though.
JohnC
2008-07-08 18:52:47 UTC
Permalink
You should always assume that code you write will be modified by someone
else when you are not around (gone to another job, on vacation, ...) and
that that person will be half as intelligent as you are.
Thus, CLARITY should be the primary goal, not whether you find it obvious or
not.
Based on this line of reasoning, I would definitely have to go with:

if ( a == b )
y = x + 1;
else
y = x;

It is immaterial whether or not the line
y = x + ( a == b );
would work or not.

John
Duane Hebert
2008-07-08 19:10:46 UTC
Permalink
Post by JohnC
You should always assume that code you write will be modified by someone
else when you are not around (gone to another job, on vacation, ...) and
that that person will be half as intelligent as you are.
Thus, CLARITY should be the primary goal, not whether you find it obvious
or not.
if ( a == b )
y = x + 1;
else
y = x;
It is immaterial whether or not the line
y = x + ( a == b );
would work or not.
I have to agree with that, especially if you use actual variables
the first example will have the intent clearly documented. What
would be the value of the second example?

Even assuming that we're all smart enough to know that
the comparison returns 0 or 1, then we have to understand
why this is important. This is clear from the first example.
Besides, I find it preferable to treat == as a bool.
Vladimir Grigoriev
2008-07-09 10:04:00 UTC
Permalink
Post by JohnC
You should always assume that code you write will be modified by someone
else when you are not around (gone to another job, on vacation, ...) and
that that person will be half as intelligent as you are.
Thus, CLARITY should be the primary goal, not whether you find it obvious
or not.
if ( a == b )
y = x + 1;
else
y = x;
It is immaterial whether or not the line
y = x + ( a == b );
would work or not.
John
If we will admit that the next programmer will be "half as intelligent as
you are" then this will lead to degradation of programming in whole. :) I
think that the task of any programmer is to raise his knowledge in the field
of programming.
As for initial expression I guess that the record

if ( ( number_of_lines + ( page == FIRST_PAGE ) ) == LINES_PER_PAGE )
bla, bla,bla...

is more clear than

if ( ( number_of_lines + ( ( page == FIRST_PAGE ) ? 1 : 0 ) ) ==
LINES_PER_PAGE )
bla, bla,bla...

The second record is too heavy for perception by glance.
Moreover in binary arithmetic operations sometimes it is better to use
explressions like a + ( b == c ) then to split it on several if-then-else
statements.
For example I think that using the expression below

iRoundedLen = ( iSomeLen + 3 ) & -4;

is a general practice instead of using (the snip is taken from real code)

i = ( tSomeLen % 4);
if(i == 0)
iRoundedLen = iSomeLen ;
else
iRoundedLen = iSomeLen + 4 - i;

Vladimir Grigoriev
JohnC
2008-07-09 11:37:05 UTC
Permalink
Post by Vladimir Grigoriev
if ( ( number_of_lines + ( page == FIRST_PAGE ) ) == LINES_PER_PAGE )
bla, bla,bla...
I think this is your meaning (if it isn't, I apologize for being half as
intelligent as you are):

NmbLinesAllowedOnThisPage = LINES_PER_PAGE ;
if ( page == FIRST_PAGE )
NmbLinesAllowedOnThisPage --;
...
if( number_of_lines == NmbLinesAllowedOnThisPage )
{
...
{

As to the issue of "instructing" other programmers, I believe that it is
more important to instruct them to write clear, unambiguous code (by
example) than to write "tricky" code. The only thing that "tricky" code is
worth is the inflation to your ego when someone comes to you and says: "I
can't understand this line of code that you wrote. Could you please explain
it?"

There are few things that I expect from code: (1) correctness and (2)
maintainability. I expect the compiler to worry about everything else.

John
Vladimir Grigoriev
2008-07-09 12:07:29 UTC
Permalink
Post by JohnC
Post by Vladimir Grigoriev
if ( ( number_of_lines + ( page == FIRST_PAGE ) ) == LINES_PER_PAGE )
bla, bla,bla...
I think this is your meaning (if it isn't, I apologize for being half as
NmbLinesAllowedOnThisPage = LINES_PER_PAGE ;
if ( page == FIRST_PAGE )
NmbLinesAllowedOnThisPage --;
...
if( number_of_lines == NmbLinesAllowedOnThisPage )
{
...
{
As to the issue of "instructing" other programmers, I believe that it is
more important to instruct them to write clear, unambiguous code (by
example) than to write "tricky" code. The only thing that "tricky" code
"I can't understand this line of code that you wrote. Could you please
explain it?"
I guess you called this code "tricky" because you write already for a long
time in C++ not in C. In fact C and C++ are different languages even then
when we are speaking about built-in types. In many books on C this "trick"
is shown. Moreover C++ has also its own tricks which due to some books for
example of Scott Myers become known. However they are not obvious for a
reader of a C++ program.
If we take into account readability and simplicity I think the original code
is clear enough.
A reader understands that the difference lies in that whether it is the
first page or other usual page.

( number_of_lines + ( page == FIRST_PAGE ) )

Why should he think that a 479 or -12 is added?! Intuitively even if he does
not know C he understands that a 1 is added. As for if-then-else I have
said already that very othen nested and numerous if-then-else's make code
difficult to read. It is my opinion. You have your own opinion. However in
this concrete case I don't think that you opinion is much better then my
opinion.

Vladimir Grigoriev
Old Wolf
2008-07-15 15:18:16 UTC
Permalink
Post by Vladimir Grigoriev
As for initial expression I guess that the record
if ( ( number_of_lines + ( page == FIRST_PAGE ) ) ==
is more clear than
if ( ( number_of_lines + ( ( page == FIRST_PAGE ) ? 1 : 0 ) )
Of course it is. Although you should consider that your
code will be read by other maintenance programmers, that
doesn't mean you should obfuscate it in case somebody reads
it who learned C off the back of a cereal box.

I think it is a great advantage of C compared to other
languages that you can clearly and concisely express this
concept, rather than having a 5-line conditional block.
Post by Vladimir Grigoriev
For example I think that using the expression below
iRoundedLen = ( iSomeLen + 3 ) & -4;
is a general practice instead of using (the snip is taken from real code)
i = ( tSomeLen % 4);
if(i == 0)
iRoundedLen = iSomeLen ;
else
iRoundedLen = iSomeLen + 4 - i;
This example is only good if 'iSomeLen' is unsigned int or
unsigned long; otherwise you are doing bitwise operations on
signed quantities, which does not have well-defined results.

Chris Uzdavinis (TeamB)
2008-07-09 16:20:51 UTC
Permalink
Post by JohnC
You should always assume that code you write will be modified by someone
else when you are not around (gone to another job, on vacation, ...) and
that that person will be half as intelligent as you are.
Thus, CLARITY should be the primary goal, not whether you find it obvious or
not.
if ( a == b )
y = x + 1;
else
y = x;
It is immaterial whether or not the line
y = x + ( a == b );
would work or not.
Clarity is very important, but one must ask: clear for whom?
Some complex solutions can still be very clear in code, but the
solution is inherently difficult. Some solutions are simple to
understand in the naive case, but a decent implementation requires a
more ... creative ... solution.

Any problem involving domain-specific knowledge is going to be clear
to those who work in that area, and not-so-clear to others.

For example, if you do a lot of low-level work twiddling bits, then
some things are second nature to you that are as foreign as Urdu to
others. That doesn't mean you shouldn't code it, it means that others
need to have a certain proficiency. I suggest that we define
"clarity" of code to be "clear to a competant programmer familiar in
the problem domain."

Problem:

How do you find 2 numbers that differ by no more than 2 bits?

The question is easy to comprehend, but the naive
loop-through-the-bits solution is clunky, slow(er), and probably the
first thing that most everyone thinks of, but argubly the worst
solution. Implementing an idea that is clear using clunky code is
catering to the wrong ideal. It certainly "works" but is anything but
beautiful. Below, I wrote 3 implementations to the problem stated
above, each better than the previous, though the first two have a lot
in common and I consider poor solutions. IMHO, the final solution is
light, elegant, fast, visually pleasing, and is clearly the optimal
solution. (Only "downside" is that it's a little more complicated
due to the bitwise logic behind it.)


bool differs_2_bits_at_most_BAD(
unsigned int num1,
unsigned int num2)
{
int diff_count = 0;

for (int i = 0; i < 32; ++i)
{
if ((num1 & 1) != (num2 & 1))
{
++diff_count;
if (diff_count > 2)
{
return false;
}
}
num1 >>= 1;
num2 >>= 1;
}
return true;
}


bool differs_2_bits_at_most_BETTER(
unsigned int num1,
unsigned int num2)
{
int diff_count = 0;
unsigned int bits = num1 ^ num2;
unsigned int mask = 1;
for (int i = 0; i < 32; ++i)
{
if (bits & mask)
{
if (++diff_count > 2)
{
return false;
}
}
mask <<= 1;
}
return true;
}


bool differs_2_bits_at_most_BEST(
unsigned int num1,
unsigned int num2)
{
unsigned int bits = (num1 ^ num2);
bits &= bits - 1;
bits &= bits - 1;
return bits == 0;
}


Which is the clearest?
--
Chris (TeamB);
JohnC
2008-07-09 17:36:27 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
bool differs_2_bits_at_most_BEST(
unsigned int num1,
unsigned int num2)
{
unsigned int bits = (num1 ^ num2);
bits &= bits - 1;
bits &= bits - 1;
return bits == 0;
}
Which is the clearest?
--
Chris (TeamB);
Once one sees what "bits &= bits - 1;" is doing, it is quite elegant.
In fact, if I understand it correctly, it is generalizable by just repeating
the line the desired number of times or putting it into a loop.

I agree with you that the context is important. For example, there are many
things that one might do in numerical programming that anyone lacking a
background in numerical programming would not understand and/or would think
to be unnecessary. The importance of machine epsilon and the whole issue of
comparison of floating point values come to mind immediately as examples.

Best,
John
Vladimir Grigoriev
2008-07-10 09:50:31 UTC
Permalink
My opinion is that most of us get used to program C++ that forget some
peculiarities of C in particularity that such expression in C as ( a == b )
is of type integer and equal to 1 or 0.

Vladimir Grigoriev
Duane Hebert
2008-07-10 14:15:07 UTC
Permalink
Post by Vladimir Grigoriev
My opinion is that most of us get used to program C++ that forget some
peculiarities of C in particularity that such expression in C as ( a ==
b ) is of type integer and equal to 1 or 0.
And you think this is a bad thing? <g>
Helmut Giese
2008-07-10 09:57:23 UTC
Permalink
Hi Chris,
very nice example - I love it.
Many thanks
Helmut Giese
Post by Chris Uzdavinis (TeamB)
bool differs_2_bits_at_most_BEST(
unsigned int num1,
unsigned int num2)
{
unsigned int bits = (num1 ^ num2);
bits &= bits - 1;
bits &= bits - 1;
return bits == 0;
}
Chris Uzdavinis (TeamB)
2008-07-10 18:23:28 UTC
Permalink
Post by Helmut Giese
Hi Chris,
very nice example - I love it.
Many thanks
Helmut Giese
Post by Chris Uzdavinis (TeamB)
bool differs_2_bits_at_most_BEST(
unsigned int num1,
unsigned int num2)
{
unsigned int bits = (num1 ^ num2);
bits &= bits - 1;
bits &= bits - 1;
return bits == 0;
}
When I saw it, I thought it was pretty awesome too. I wish I could
take credit, but I stumbled this in volume 3 of Knuth.

Once I "got it", the applicability started to grow. The value

n & (n-1)

is essentially "remove one bit from this number". Thus, in a loop you
can remove the m least significant 1 bits by applying that to its
previous result m times.

Another insight is that powers of two only have one bit set. Thus, if
n&(n-1)==0, then n is a power of 2. And so on.
--
Chris (TeamB);
Loading...