Question

Quel est le meilleur moyen de comparer sur un signe double?

Je sais que double a un « bit de signe » mais je ne sais pas si la façon dont je suis « le chercher » dans son représentant binaire est une bonne idée ou non.

questions « Interdiction d'portabilité », quelqu'un peut me dire ce qui se passe avec ce code dans 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) ) ;
  }

}

D'abord, pourquoi est à partir de 32 bits, même si je ne changeai d'un bit?

Deuxièmement, moi est-il ok pour vérifier à la 64e d'un peu double pour vérifier son signe sur MSVC ++?

Était-ce utile?

La solution

Au minimum, il y a trois comparaisons qui -must- Happen

  1. signe extrait d'un
  2. signe extrait de b
  3. comparer a et b pour l'égalité

Il n'y a aucun moyen d'éviter ces trois choses.

Vous pouvez faire une and, vous pouvez faire un less than, ne compte pas vraiment qui - vous pourriez -probably- trouver un moyen de refroidissement / intelligent / difficile de le faire d'une autre manière aussi. Mais vous allez encore avoir besoin d'avoir ces trois opérations élémentaires. Il y a aussi pas besoin de trop compliquer ce. Si vous cherchez quelque chose à coller sur une ligne, vous pouvez faire ceci:

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

Ici, j'extraire le bit et les xor'ing. Si le bit est le même, le XOR sera 0 (false) - si les bits sont différents, le XOR sera 1 (vrai). Avec un bon commentaire expliquant ce que vous faites et pourquoi, c'est une façon parfaitement valable de le faire.

CEPENDANT: L'exemple que vous avez donné comme « ne pas utiliser ce » est pas vraiment si mal que ça ... Il est facile à lire, qui est l'une des choses les plus importantes que vous pouvez avoir dans votre code. Il y a deux règles à l'optimisation:

  1. Ne pas le faire.
  2. (experts uniquement) Ne faites pas encore.

Ne pas sacrifier la lisibilité pour l'optimisation de quelque chose qui est déjà assez rapide repriser, et sera probablement beaucoup assez vite. : -)

Autres conseils

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

double a un bit de signe (le plus important de bits), mais de trouver le signe d'un nombre est un peu plus compliqué que cela. Voulez-vous faire la distinction entre +0,0 et -0,0? Ou entre + NaN et -Nan?

En C ++ 11, on nous a donné std::signbit retours true si négatif , et false autrement.

Compte tenu de deux doubles, a et b nous pouvons comparer leurs signes avec == ou !=:

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

Live Demo


std::signbit supports double, float, long double, et tous les types intégraux. Il peut même gérer les valeurs NaN.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top