Sign of a number ...

  • Thread starter =?ISO-8859-1?Q?Konrad_M=FChler?=
  • Start date
?

=?ISO-8859-1?Q?Konrad_M=FChler?=

Hi,

a simple question:

Which standard function in c++ gives me the sign of a number?

Thanks
Konrad
 
V

Victor Bazarov

Konrad said:
a simple question:

Which standard function in c++ gives me the sign of a number?

There is no standard function in C++ (mostly because there is no
agreement on what such function would return for 0, for example).
Why do you ask? Is it difficult to write? Are you concerned
with performance?

V
 
R

red floyd

Konrad said:
Hi,

a simple question:

Which standard function in c++ gives me the sign of a number?

In addition to what Victor said...

There's always std::less<>().
 
M

mathieu

There is no standard function in C++ (mostly because there is no
agreement on what such function would return for 0, for example).
Why do you ask? Is it difficult to write? Are you concerned
with performance?


You can do it with bits field:

#include <iostream>

template <typename T>
struct Sign
{
bool S:1;
T Remaining:(sizeof(T)-1);
};

int main()
{
Sign<int> z;
int zero = 0;
int minusone = -1;
float minuszero = -0.0;
memcpy(&z,&zero,sizeof(zero));
std::cout << z.S << std::endl;
memcpy(&z,&minusone,sizeof(minusone));
std::cout << z.S << std::endl;

Sign<int> zz;
memcpy(&zz,&minuszero,sizeof(minuszero));
std::cout << z.S << std::endl;
return 0;
}

In which case 0 and -0 are different, this will not be compatible with
a solution using '<' and/or '>'

HTH
-Mathieu
 
P

Philip Potter

mathieu said:
You can do it with bits field:

#include <iostream>

template <typename T>
struct Sign
{
bool S:1;
T Remaining:(sizeof(T)-1);
};

int main()
{
Sign<int> z;
int zero = 0;
int minusone = -1;
float minuszero = -0.0;
memcpy(&z,&zero,sizeof(zero));
std::cout << z.S << std::endl;
memcpy(&z,&minusone,sizeof(minusone));
std::cout << z.S << std::endl;

Sign<int> zz;
memcpy(&zz,&minuszero,sizeof(minuszero));
std::cout << z.S << std::endl;
return 0;
}

In which case 0 and -0 are different, this will not be compatible with
a solution using '<' and/or '>'

I doubt that any of this is guaranteed to work, and even if it is, it's
horrible code. What's wrong with 'if (val>0.0)'?
 
V

Victor Bazarov

mathieu said:
You can do it with bits field:

Why are you replying to me? If I were to do it, I'd simply write

template<class T> int sign(T t) {
return t < 0 ? -1 : t > 0 ? 1 : 0;
}

but that's just one definition of 'sign' (another treats 0 as
a positive value). Besides, the OP may want to return T instead
of 'int'...
#include <iostream>

template <typename T>
struct Sign
{
bool S:1;
T Remaining:(sizeof(T)-1);

'sizeof' does NOT return the number of bits in the object...
};

int main()
{
Sign<int> z;
int zero = 0;
int minusone = -1;
float minuszero = -0.0;
memcpy(&z,&zero,sizeof(zero));
std::cout << z.S << std::endl;
memcpy(&z,&minusone,sizeof(minusone));
std::cout << z.S << std::endl;

Sign<int> zz;
memcpy(&zz,&minuszero,sizeof(minuszero));
std::cout << z.S << std::endl;
return 0;
}

In which case 0 and -0 are different, this will not be compatible with
a solution using '<' and/or '>'

HTH

'fraid it don't. Have you actually tested your program before posting?

V
 
M

mathieu

Why are you replying to me?

my bad, sorry.
'sizeof' does NOT return the number of bits in the object...
ooops...





'fraid it don't. Have you actually tested your program before posting?

I meant to say that

if ( t < 0 ) return 0;
else return 1;

is not compatible with the bit fields solution...

and indeed I did test my solution before posting:

$ gcc --version
gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

-Mathieu
 
V

Victor Bazarov

mathieu said:
[..]
I meant to say that

if ( t < 0 ) return 0;
else return 1;

is not compatible with the bit fields solution...

It's not "compatible" with any known 'sign' definitions either.
I am still unsure why you'd need to create some bitfield monster
when a simple stand-alone function would do...

V
 
P

Philip Potter

Victor said:
mathieu said:
[..]
I meant to say that

if ( t < 0 ) return 0;
else return 1;

is not compatible with the bit fields solution...

It's not "compatible" with any known 'sign' definitions either.
I am still unsure why you'd need to create some bitfield monster
when a simple stand-alone function would do...

I believe what he's trying to do is read the floating-point sign bit and
return that. This distinguishes between positive and negative zero, but
that distinction is not always useful.
 
M

Markus Moll

Hi
Which standard function in c++ gives me the sign of a number?

Assuming that you have a compiler that supports the C99-library, there
is "int signbit (X)" in math.h.

From the manpage:
‘signbit’ is a generic macro which can work on all real floating-point
types. It returns a non-zero value if the value of X has its sign bit
set.
This is not the same as ‘x < 0.0’, because IEEE 754 floating point
allows zero to be signed. The comparison ‘-0.0 < 0.0’ is false, but
‘signbit (-0.0)’ will return a non-zero value.

Markus
 
V

Victor Bazarov

Markus said:
Assuming that you have a compiler that supports the C99-library, there
is "int signbit (X)" in math.h.

From the manpage:
'signbit' is a generic macro which can work on all real
floating-point types. It returns a non-zero value if the value of X
has its sign bit set.
This is not the same as 'x < 0.0', because IEEE 754 floating
point allows zero to be signed. The comparison '-0.0 < 0.0' is
false, but 'signbit (-0.0)' will return a non-zero value.

Are you saying that the 'sgn' function in Mathematica is equivalent
to this 'signbit'? Or 'Sgn' function in VB is? I beg to differ.
BTW, does the negative zero compare equal to [the positive] zero?

V
 
J

James Kanze

Are you saying that the 'sgn' function in Mathematica is equivalent
to this 'signbit'? Or 'Sgn' function in VB is?

I don't know about those, but the sign function in Fortran
returned -1, 0 or 1, and returned 0 for both plus and minus 0
(like the function you proposed).
I beg to differ.
BTW, does the negative zero compare equal to [the positive] zero?

Yes, by law (i.e. the C and the C++ standards). In practice,
there are very few ways you can distinguish between the two:
1/-0.0 returns -Inf, whereas 1/+0.0 returns +Inf (and I think
you can compare [+-]Inf with 0.0, so if you had a zero, and
wanted to know its sign, you could do "if ( 1/zero < 0.0 )", or
something like that).

I'm not a specialist in numerical analysis, so I'm probably
putting my foot in my mouth, but about the only time I can see
the sign bit being useful is when outputting to a binary format.
A truely portable output would use signbit(), ldexp() and
frexp() to extract the sign, the exponent and the mantissa
separately, then recombine them according to the requirements of
the format. Something like:

oxdrstream&
oxdrstream::eek:perator<<(
float source )
{
BytePutter dest( *this ) ;
bool isNeg = signbit( source ) ;
if ( isNeg ) {
source = - source ;
}
int exp ;
if ( source == 0.0 ) {
exp = 0 ;
} else {
source = ldexp( frexp( source, &exp ), 24 ) ;
exp += 126 ;
}
uint32_t mant = source ;
dest.put( (isNeg ? 0x80 : 0x00) | exp >> 1 ) ;
dest.put( ((exp << 7) & 0x80) | ((mant >> 16) & 0x7F) ) ;
dest.put( mant >> 8 ) ;
dest.put( mant ) ;
return *this ;
}

If you know you've got IEEE internally, of course, you can just
memcpy into a uint32_t, and output that as you would an unsigned
int. (Surprisingly, however, at least on a Sun Sparc, the above
is not outrageously slow.)
 
A

Alf P. Steinbach

* James Kanze -> Victor Bazarov:
BTW, does the negative zero compare equal to [the positive] zero?

Yes, by law (i.e. the C and the C++ standards). In practice,
there are very few ways you can distinguish between the two:
1/-0.0 returns -Inf, whereas 1/+0.0 returns +Inf (and I think
you can compare [+-]Inf with 0.0, so if you had a zero, and
wanted to know its sign, you could do "if ( 1/zero < 0.0 )", or
something like that).

I'm not a specialist in numerical analysis, so I'm probably
putting my foot in my mouth,

Yep. :)

I'm not a numerical analyst either, but I know of one example here.

but about the only time I can see
the sign bit being useful is when outputting to a binary format.

The square root function for complex result propagates the sign bit so
as to keep ordinary mathematical relationships intact. If not for that,
graphing software could much more easily produce graphs that jumped all
over the place instead of being nicely connected. In short, negative
zero plays a crucial rôle in complex arithmetic.

Cheers,

- Alf
 

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
474,164
Messages
2,570,901
Members
47,439
Latest member
elif2sghost

Latest Threads

Top