signe de comparer deux doubles
-
03-10-2019 - |
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 ++?
La solution
Au minimum, il y a trois comparaisons qui -must- Happen
- signe extrait d'un
- signe extrait de b
- 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:
- Ne pas le faire.
- (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";
}
std::signbit
supports double
, float
, long double
, et tous les types intégraux. Il peut même gérer les valeurs NaN
.