Voici une implémentation favorable aux branchements :
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
À moins que vos données ne comportent des zéros dans la moitié des nombres, le prédicteur de branche choisira l'une des branches comme étant la plus commune. Les deux branches n'impliquent que des opérations simples.
Alternativement, sur certains compilateurs et architectures de CPU, une version complètement sans branche peut être plus rapide :
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
Cela fonctionne pour Format de virgule flottante binaire double précision IEEE 754 : binary64 .
21 votes
Que doit-il retourner pour 0 ?
78 votes
@Craig McQueen ; cela dépend si c'est un zéro positif ou un zéro négatif.
1 votes
J'ai remarqué que vous avez spécifié la valeur de retour comme un nombre entier. Cherchez-vous une solution qui prend des entiers ou des nombres à virgule flottante ?
0 votes
@ysth : C'est vrai pour les flottants mais pas pour les ints, donc je suppose que la question est : est-ce que le questionneur est intéressé par les flottants ou les ints ?
9 votes
@ysth @Craig McQueen, faux pour les flottants aussi, non ? sgn(x)'s définition dit de retourner 0 si
x==0
. Selon IEEE 754 le zéro négatif et le zéro positif doivent être comparés comme égaux.0 votes
@RJFalconer : Je ne comprends pas votre commentaire. Que dites-vous qui est faux ?
9 votes
@ysth "cela dépend du zéro positif ou du zéro négatif". En fait, ce n'est pas le cas.
0 votes
@RJFalconer Le
sgn()
de votre commentaire est une vision raisonnable de la façon de gérer les zéros. OP ne spécifie qu'indirectement le signe du zéro avec un lien. Une autre vision raisonnable du "signe" est de retourner 1,-1 sur +zéro,-zéro. Parfois, le signe de zéro fait la différence . Cela dépend des besoins de l'utilisateur. Voir aussi NaN est un considération selon les indications de l'OPfloat
.6 votes
Je commente tardivement, mais concernant les zéros signés, une autre option raisonnable est que sgn(x) renvoie x, lorsque x est zéro. En d'autres termes, vous obtenez 0, mais c'est un zéro signé avec le même signe que l'entrée. @RJFalconer Dans les cas relativement peu nombreux où les zéros signés importent, vous obtenez une réponse sensée, et dans les autres cas, cela ne fait aucune différence.
1 votes
Quel résultat doit être renvoyé pour une valeur NaN ?
0 votes
C ou C++ - choisissez-en un, pas les deux. Ce sont des langages différents.
0 votes
C99, C++ : cplusplus.com/reference/cmath/signbit