optimizing an expression

C

Corvus

I am looking for other ways to write the following in as few lines as
possible, but I think I have hit the limit...

x -= x/abs(x)

So far, I have come up with this(it seems to work anyway):

x -= x > 0 ? 1 : -1

Can anyone see any other way of expressing this as a single expression?

Corvus
 
B

BGB / cr88192

Corvus said:
I am looking for other ways to write the following in as few lines as
possible, but I think I have hit the limit...

x -= x/abs(x)

So far, I have come up with this(it seems to work anyway):

x -= x > 0 ? 1 : -1

Can anyone see any other way of expressing this as a single expression?


x -= 1-((!(x>0))<<1);

or, do you mean "sensible"?...
 
T

Tim Prince

Corvus said:
I am looking for other ways to write the following in as few lines as
possible, but I think I have hit the limit...

x -= x/abs(x)

So far, I have come up with this(it seems to work anyway):

x -= x > 0 ? 1 : -1

Can anyone see any other way of expressing this as a single expression?

Ignoring the case x == 0, assuming it is an int type, as you have done:
x += 1 - 2*(x>0);
(x>0)? x-- : x++ ;
.....
Before 1975, there were practical languages with few alternate syntactic
choices for the same result, but C put an end to that.
 
C

Corvus

BGB said:
x -= 1-((!(x>0))<<1);

or, do you mean "sensible"?...

Interesting...I honestly had never thought of that...and no, it doesn't
have to be sensible. :)

Corvus
 
C

Corvus

Tim said:
Ignoring the case x == 0, assuming it is an int type, as you have done:
x += 1 - 2*(x>0);
(x>0)? x-- : x++ ;
....
Before 1975, there were practical languages with few alternate syntactic
choices for the same result, but C put an end to that.

Nice...!
 
S

spinoza1111

I am looking for other ways to write the following in as few lines as
possible, but I think I have hit the limit...

x -= x/abs(x)

So far, I have come up with this(it seems to work anyway):

x -= x > 0 ? 1 : -1

Can anyone see any other way of expressing this as a single expression?

Corvus

Your solutions all have a bug: what if x is zero? Don't optimize until
you've debugged.

It appears that you are trying to calculate the value of the signum
function, which is NOT -1 for zero, nor undefined. Signum is 1 for x >
0, 0 for x==0, -1 for x < 0.

Do it straightforwardly:

x -= x > 0 ? 1 : (x < 0 ? -1 : 0)

A more reliable way would be to package it as a function, and, in the
function, test x for all possible values. In the most general case, x
does not have to be positive, negative or zero: in a weakly typed OO
system it might be a complex number.

x -= signum(x)

float signum(int x)
{
if (x > 0) return 1;
if (x < 0) return -1;
if (x == 0) return 0;
printf("Fatal error, alack the day\n");
}

Of course, in the above, x's being an int guarantees that the last
test is unnecessary, but not in the most general case. For reliability
it never hurts, when classifying something, to explicitly test it for
all possible cases rather than "falling through" to a "default" value;
note that the shift into traditional "programmerese" is a signal that
we're about to revert to barbarism as is also the case when a
programmer starts raving about "buffers": when programmers talk about
"falling through" they mean "I am probably missing something, and
indeed I feel like Alice in the rabbit hole".

I wouldn't use the third test in implementing signum if it can declare
its parameter as one of short, int, long, float or double because in
each case, the runtime, including the famous goddamn stack, guarantees
that x will be zero when not positive or negative...

....except (and this is important, so wake the Christ up) in certain
floating point applications where it might make perfect sense to do
this: I can easily imagine some goddamn scenario where float or double
x is not greater than, less than, or equal to zero, and code inserted
by some slob to catch this when it happens on alternate Tuesdays
during a gibbous moon.

Of course, the fun rilly starts when you implement SIGNUM, a macro: oh
dearie me how did I do that:

#define SIGNUM(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0))

(Ben Bacarisse will probably find ten real bugs in the above macro).

This macro should probably test for all three possibilities since we
have absolutely no idea what x is!

#define SIGNUM(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : ((x) == 0 ? 0 :
errorHandling())))

There probably are also ways of punning on the representation of
Boolean values as numbers:

#define SIGNUM(x) (x) ? ((x) > 0 ? 1 : -1) : 0

oh gee that saves one jillionth of a terapicosecond.

The best solution? Find a complete math library which defines signum.
 
S

spinoza1111

Ignoring the case x == 0, assuming it is an int type, as you have done:

"Ignoring the case where x==0" is a bug waiting to strike. It appears
to me that nobody told the OP that in statistics and other math,
signum is zero when x is zero.
 
K

Keith Thompson

Corvus said:
I am looking for other ways to write the following in as few lines as
possible, but I think I have hit the limit...

x -= x/abs(x)

So far, I have come up with this(it seems to work anyway):

x -= x > 0 ? 1 : -1

Note that these are not equivalent; when x == 0, the first invokes
undefined behavior, and the second sets x to 1.
Can anyone see any other way of expressing this

if (x > 0) {
--x;
}
else {
--x;
}
as a single expression?

Um, why do you want it as a single expression? It's not likely to be
either clearer or more efficient.

If you insist, you could write it as:

x > 0 ? --x : ++x;

but it's likely to generate the same code.

Rule of thumb: If a ?: operator can be written equivalently as an
if-else statement, write it as an if-else statement (unless it's
part of a macro definition).
 
S

spinoza1111

Note that these are not equivalent; when x == 0, the first invokes
undefined behavior, and the second sets x to 1.


if (x > 0) {
    --x;}

else {
    --x;

}

Um, why do you want it as a single expression?  It's not likely to be
either clearer or more efficient.

If you insist, you could write it as:

    x > 0 ? --x : ++x;

but it's likely to generate the same code.

Rule of thumb: If a ?: operator can be written equivalently as an
if-else statement, write it as an if-else statement (unless it's
part of a macro definition).

Thumb of rule: ignore the bug while helping the guy implement signum
incorrectly. I believe that he is implementing something where the
user wants signum and x may be zero, where the function should return
zero, but nobunny has told him this.

Also, I would question whether it's clearer to use if then else
than ?:. Granted the syntax is pretty much unique to C, but much worse
is unique to C. Using ?: shows awareness that while mathematics is not
part of logic, logic is part of mathematics.

A pragmatic argument for using C "statements" in place of C
"expressions" would be that on primitive debuggers it is easier to
step through complicated logic. But many modern debuggers allow
stepthrough of expressions as well, and debugging needs should not
control.
 
S

Stefan Ram

Corvus said:
I am looking for other ways to write the following in as few
lines as possible, but I think I have hit the limit...
x -= x/abs(x)
x -= x > 0 ? 1 : -1

One line is a natural limit for the size of an expression,
because the only text with fewer lines is the empty text »«,
but this is not an expression. So you can not write an
expression with less than at least one line.

However, you might be able to reduce the number of lines
an expression takes by adding a comment:

x -= x/abs(x) ////////////////////////////////////////////////

. Now the expression only takes about 0.25 lines, that is,
less than one line, because about 75 percent of the line are
being filled with the comment.
 
B

bartc

Corvus said:
I am looking for other ways to write the following in as few lines as
possible, but I think I have hit the limit...

x -= x/abs(x)

So far, I have come up with this(it seems to work anyway):

x -= x > 0 ? 1 : -1

Can anyone see any other way of expressing this as a single expression?

Both your examples are already single expressions, and are already expressed
in a single line.

Is x an int or float? If it's an int, and the range of values is known to be
small, you can use a table which maps x to x/abs(x), then use:

x = table[x]

The table can also take care of x==0. While the table will take up
additional lines, it means you can use a simpler assignment, if that was the
idea.

For unknown ranges of ints, it seems your code just increments or decrements
x towards 0. If x is not assigned to elsewhere, you can use an extra
variable like this:

dx = x<0 ? 1 : -1

Then you can just use this, assuming it's in some kind of loop:

x += dx

although you have to figure out what to do when x reaches zero.
 
B

Ben Bacarisse

Keith Thompson said:
Note that these are not equivalent; when x == 0, the first invokes
undefined behavior, and the second sets x to 1.

Also, the former is undefined if abs(x) can't be represented which is
a practical concern on many machines when x == INT_MIN.

<snip>
 
J

James Dow Allen

Rule of thumb: If a ?: operator can be written equivalently as an
if-else statement, write it as an if-else statement (unless it's
part of a macro definition).

I think we'd all agree that "cutesy" shortcuts to achieve a
false keystroke economy are wrong, but this statement goes much
too far. It seems to assume that "if else" is more readable
than "? :" but that should *not* be the case for a C programmer.

I often string together ?, : and/or && and || into an involved
expression, and add newlines and tabs to make it easy to read.
IMHO the if/else equivalent would be harder to read because of
all the "if/else" clutter.

Surely none of us prefer Cobol's
ADD OVERTIME TO SALARY
or whatever it is, over C's
salary += overtime;
Not to extend the same courtesy to C's beautiful " ? : "
would be to patronize the beginning C programmer.

James Dow Allen
 
S

Stefan Ram

spinoza1111 said:
It appears that you are trying to calculate the value of the signum
function, which is NOT -1 for zero, nor undefined. Signum is 1 for x >
0, 0 for x==0, -1 for x < 0.

For signum,

( x > 0 )-( x < 0 )

might be efficient, because it can often be compiles to
three instructions and does not contain branches.

Unlike solutions involving "x >> 31" it does not depend on
details of the representation and is also quite readable.
 
M

Mark Bluemel

  For signum,

( x > 0 )-( x < 0 )

  might be efficient, because it can often be compiles to
  three instructions and does not contain branches.

  Unlike solutions involving "x >> 31" it does not depend on
  details of the representation and is also quite readable.

For some values of "readable", I guess. I quite like it, but I'm not
convinced that this sort of variation on Perl Golf is helpful for real-
world code. I've debugged other people's code at 3am after spending
the evening trying to get a baby to go to sleep, and frankly I'd curse
them if their code wasn't transparent. I'm with Spinoza here - be
explicit.
 
B

bartc

Richard Heathfield said:
In


The expression /is/ explicit.

Not as explicit as, say:

intsign(x)

The original expression requires some analysis as to what it's trying to
achieve.

And if the variable name was longer, and the expression appears many times
then it requires more analysis to make sure no mistake has been made, such
as one or both of the > or < being the right way around, and the same name
was used in each half. (And if there is a discrepancy, was it a mistake, or
is it actually something unrelated.)
 
S

spinoza1111

In




It is a most readable expression, once you get used to the notion that
relational expressions have values in their own right. (It is not
unreasonable to assume a certain level of "literacy" in the reader
when assessing readability.)

Nobody has yet conceded the main problem, that the OP is trying to
implement signum and failing by giving a **wrong answer** when x is
zero but the above solution seems to address this problem.

It's amazing that so few people here seem to know signum. Disturbing,
as well.
I regularly use the same idiom in real-world code, in comparison
functions, and I don't see why you would think it to be unsuitable
for the real world.


That's not absolute proof that you're wrong, but it's not a hopeful
sign.

Personality based comments are childish and have no place here. I'm
real tired of how you consistently transform technical issues into
personal icons. You have two registers: uncritical worship of some
personality (such as Ada Augusta) whose status impresses you, and
uncritical trashing when you think the target is a safe place to shit
on.

It's lower middle class and Fascistic. Cease and desist or leave on a
holiday in Spain.
 
G

gwowen

It is a most readable expression, once you get used to the notion that
relational expressions have values in their own right. (It is not
unreasonable to assume a certain level of "literacy" in the reader
when assessing readability.)

We must have wildly different ideas about readability. To me readable
code is code that expresses intent clearly. "Programs are meant to be
read by humans and only incidentally for computers to execute".

x -= (x>0)-(x<0);

does not express intent clearly. One can work out what it does quite
easily, but that's still work. It's all about "how" and not about
"why".

/* ... or a macro, obviously ... */
static inline int signum (int x){
return (x>0)-(x<0);
}
/* ... */
x -= signum(x);

is the best of both worlds.
 
S

spinoza1111

Pot, kettle, etc.

-David

No, it is not pot and kettle. If you sequence the posts, it is
consistently Richard Heathfield who starts the campaign of personality
destruction. I finish it and will continue to do so because "this
animal is dangerous, it defends itself when attacked."
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top