views:

80

answers:

3

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++?

A: 
((((__int64*)(&z))*) & 0x8000000000000000) give you the sign
Andrey
+2  A: 

At a minimum, there are three comparisons that -must- happen

  1. extract sign of a
  2. extract sign of b
  3. compare a and b for equality

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:

  1. Don't do it.
  2. (Experts only) Don't do it yet.

Don't sacrifice readability for optimization of something that's already pretty darned fast, and will probably be plenty fast enough. :-)

glowcoder
A: 

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?

dan04