Domanda

Qual è il modo più veloce per confrontare segno su un double?

So che un double ha un "bit di segno", ma non sono sicuro se il modo in cui sto "cercando per esso" nella sua rep binario è una buona idea o no.

Blocco problemi "portabilità", qualcuno può dirmi che cosa sta succedendo con questo codice 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) ) ;
  }

}

In primo luogo, perché è a partire da 32 bit, anche se ho solo spostato di un bit?

In secondo luogo, è ok per me, per controllare il bit di 64 ° di un double per controllare il suo segno sulla MSVC ++?

È stato utile?

Soluzione

Come minimo, ci sono tre confronti che -must- accadono

  1. estratto segno di un
  2. estratto segno di b
  3. confrontare A e B per l'uguaglianza

Non c'è alcun modo per evitare queste tre cose.

Si può fare un and, si può fare un less than, non importa quale - si potrebbe trovare un -probably- cool / intelligente / ingannevole modo per farlo in un altro modo troppo. Ma si sta ancora andando ad avere bisogno di avere quelle tre operazioni elementari. Inoltre non c'è bisogno di complicare eccessivamente esso. Se siete alla ricerca di qualcosa da bastone su una linea, si potrebbe fare questo:

__int64 mask = 0x8000000000000000; // i think that's the right amount of 0's :-)
if( (x&mask) ^ (y&mask) ) 
  puts("different");
else
  puts("same");

Qui sto estrarre la punta e li xor'ing. Se il bit è la stessa, la xor sarà 0 (false) - se i bit sono differenti, il xor sarà 1 (true). Con un commento che spiega bene quello che stai facendo e perché, questo è un modo perfettamente valido per farlo.

TUTTAVIA: L'esempio che ha dato come "non usare questo" non è poi così male ... E 'facile da leggere, che è una delle cose più importanti che si possono avere nel codice. Ci sono due regole per l'ottimizzazione:

  1. Non farlo.
  2. (solo utenti esperti) Non ancora farlo.

Non sacrificare la leggibilità per l'ottimizzazione di qualcosa che è già abbastanza dannatamente veloce, e sarà probabilmente un sacco abbastanza veloce. : -)

Altri suggerimenti

((((__int64*)(&z))*) & 0x8000000000000000) give you the sign

double ha un bit di segno (il bit più significativo), ma trovare il segno di un numero è un po 'più complicato di così. Vuoi distinguere tra +0.0 e -0.0? O tra il + Nan e -NaN?

In C ++ 11, ci hanno dato std::signbit che restituisce true se negativo , e false altrimenti.

Dato due doppie, a e b siamo in grado di confrontare i loro segni con == o !=:

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";
}

Demo Live


supporti std::signbit double, float, long double, e tutti i tipi integrali. Si può anche gestire i valori NaN.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top