On Nov 15, 4:37 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Markus Moll wrote:
Konrad Mühler wrote:
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.
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::operator<<(
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.)
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34