Reputation: 67224
What's the fastest way to compare sign on a double
?
I know that a double
has a "sign bit" but I'm not sure if the way I'm "looking for it" in its binary rep is a good idea or not.
Barring "portability" issues, can someone tell me what's going on with this code in MSVC++?
#include <stdio.h>
int main()
{
double z = 5.0 ;
__int64 bitSign ;
__int64 *ptr ;
ptr = (__int64*)&z ;
for( __int64 sh = 0 ; sh < 65 ; sh++ )
{
bitSign = 1L << sh ; // Weird. it doesn't do 1.
printf( "Bit# %d (%llx): %lld\n",
sh, bitSign, ( (*ptr) & bitSign) ) ;
}
}
First, why is starting at bit 32, even though I only shifted by one bit?
Second, is it ok for me to check the 64th bit of a double
to check its sign on MSVC++?
Upvotes: 3
Views: 2818
Reputation: 41090
In C++11, we were given std::signbit
that returns true
if negative, and false
otherwise.
Given two doubles, a
and b
we can compare their signs with ==
or !=
:
void classify(double _lhs, double _rhs)
{
std::cout << _lhs << " and " << _rhs;
if (std::signbit(_lhs) == std::signbit(_rhs))
std::cout << " have the same sign\n";
else
std::cout << " have different signs\n";
}
std::signbit
supports double
, float
, long double
, and all integral types. It can even handle NaN
values.
Upvotes: 3
Reputation: 90995
double
does have a sign bit (the most significant bit), but finding the sign of a number is a bit more complicated than that. Do you want to distinguish between +0.0 and -0.0? Or between +NaN and -NaN?
Upvotes: 0
Reputation: 82559
At a minimum, there are three comparisons that -must- happen
There's no way to avoid those three things.
You can do an and
, you can do a less than
, doesn't really matter which - you -probably- could find a cool/clever/tricky way to do it another way too. But you're still going to need to have those three elementary operations. There's also no need to overly complicate it. If you're looking for something to stick on one line, you could do this:
__int64 mask = 0x8000000000000000; // i think that's the right amount of 0's :-)
if( (x&mask) ^ (y&mask) )
puts("different");
else
puts("same");
Here I'm extracting the bit and xor'ing them. If the bit is the same, the xor will be 0 (false) - if the bits are different, the xor will be 1 (true). With a good comment explaining what you're doing and why, this is a perfectly valid way to do it.
HOWEVER: The example you gave as "don't use this" isn't really all that bad... It's easy to read, which is one of the most important things you can have in your code. There are two rules to optimization:
Don't sacrifice readability for optimization of something that's already pretty darned fast, and will probably be plenty fast enough. :-)
Upvotes: 2