Compute the sign of a number.

J

J.W.

Hello, all,

I wanted to get some help understanding the process of computing a sign of a
number.

I tried this in my program:

#define CHAR_BIT 8
int v=-100;
int sign = v >> (sizeof(int) * CHAR_BIT - 1);

I expect the answer will be 1 since the highest bits stored in v will be 1 ,
however, the sign will give me the value of -1.

I would appreciate if somebody here could give me some hint why it turns out
to be -1 , NOT 1.

Thanks,
J.W.
 
L

Leclerc

I expect the answer will be 1 since the highest bits stored in v will be
1 , however, the sign will give me the value of -1.

I would appreciate if somebody here could give me some hint why it turns
out to be -1 , NOT 1.


Try answering following questions:
* when shifting to the right, what appears as leftmost (binary) digit,
zero or one?

* since shifting to the right is division by 2, how do you preserve sign
after shifting (i.e. division)?
 
J

Juha Nieminen

J.W. said:
I tried this in my program:

#define CHAR_BIT 8
int v=-100;
int sign = v >> (sizeof(int) * CHAR_BIT - 1);

I expect the answer will be 1 since the highest bits stored in v will be
1 , however, the sign will give me the value of -1.

When you shift a signed integral to the right, the sign bit is
duplicated for each shift. This is called "sign extension".

(I'm actually not completely sure if the C++ standard guarantees this
behavior, but it works like this in most computer architectures.)

One simple way of doing what you want is to use a conditional:

int sign = (v < 0 ? 1 : 0);

There are other ways of doing the same thing without using
conditionals, but I'm not sure there's a practical advantage (unless you
need to get that sign bit hundreds of millions of times per second).
 
D

Daniel T.

  When you shift a signed integral to the right, the sign bit is
duplicated for each shift. This is called "sign extension".

  (I'm actually not completely sure if the C++ standard guarantees this
behavior, but it works like this in most computer architectures.)

  One simple way of doing what you want is to use a conditional:

int sign = (v < 0 ? 1 : 0);

  There are other ways of doing the same thing without using
conditionals, but I'm not sure there's a practical advantage (unless you
need to get that sign bit hundreds of millions of times per second).

You could just:

bool neg = v < 0;
 
D

Daniel Pitts

J.W. said:
Hello, all,

I wanted to get some help understanding the process of computing a sign
of a number.

I tried this in my program:

#define CHAR_BIT 8
int v=-100;
int sign = v >> (sizeof(int) * CHAR_BIT - 1);

I expect the answer will be 1 since the highest bits stored in v will be
1 , however, the sign will give me the value of -1.

I would appreciate if somebody here could give me some hint why it turns
out to be -1 , NOT 1.

Thanks,
J.W.

What is the sign of 0?

Unless you have *really* good reason to do so, don't do any fancy bit
tricks.

int sign = v < 0;
 
A

Alan Johnson

Juha said:
When you shift a signed integral to the right, the sign bit is
duplicated for each shift. This is called "sign extension".

(I'm actually not completely sure if the C++ standard guarantees this
behavior, but it works like this in most computer architectures.)

Just to be thorough, it is not guaranteed. The relevant bit of the
standard is 5.8.3:

The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an
unsigned type or if E1 has a signed type and a nonnegative value, the
value of the result is the integral part of the quotient of E1 divided
by the quantity 2 raised to the power E2. If E1 has a signed type and a
negative value, the resulting value is implementation-defined.
 
J

James Kanze

When you shift a signed integral to the right, the sign bit is
duplicated for each shift. This is called "sign extension".
(I'm actually not completely sure if the C++ standard
guarantees this behavior, but it works like this in most
computer architectures.)

It's implementation defined. From a QoI point of view, however,
I would expect sign extension whenever the architecture has
direct hardware support for it; i.e. when using sign extension
has no additional runtime cost.

One obvious way to avoid it would be to convert the argument to
the corresponding unsigned type (which never has sign extension,
because there is no sign). However...
One simple way of doing what you want is to use a conditional:
int sign = (v < 0 ? 1 : 0);

This also has the advantage of saying explicitly what he's
trying to do. (Intuitively, of course, I'd expect something
named "sign" to correspond more or less to the old Fortran
definition: -1 for negative, 0 for 0, and 1 for positive. I'd
use something like "isNegative", and a type bool, if that's what
I really wanted.)
There are other ways of doing the same thing without using
conditionals, but I'm not sure there's a practical advantage
(unless you need to get that sign bit hundreds of millions of
times per second).

Even then, I'd wait and see what the compiler did with it. I've
used at least one compiler that would have implemented your code
by shifting left (putting the sign in the carry bit), then
clearing a register, and adding 0 with carry to it. And I've
worked on one machine where shifting was horribly expensive,
with a cost proportional to the number of bits being shifted.
(For what it's worth, none of the compilers I have access to use
a branch instruction in your code, at least when optimization is
turned on.)
 
J

James Kanze

You could just:
bool neg = v < 0;

That's a good point, but the original code used an int. You
could count on the implicit conversion:

int neg = v < 0 ;

but if the desired result is an int, with values 0 or 1, rather
than a bool, with values false and true, I'd prefer Juha's
expression. It makes this more explicit.
 
G

Gernot Frisch

template <class T> T sgn(const T& num)
{
return num > 0 ? 1 : num<0 ? -1 : 0;
}
 

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

Forum statistics

Threads
474,163
Messages
2,570,897
Members
47,434
Latest member
TobiasLoan

Latest Threads

Top