É muito fácil comparar duplos positivos: a normalização garante-nos que dos números com expoentes diferentes, quanto maior for aquele cujo expoente é maior, e dos números com o mesmo expoente, maior será aquele cuja mantissa é maior. O padrão IEEE 754 colocou cuidadosamente o expoente nos bits de ordem superior, portanto, os duplos positivos podem ser comparados simplesmente como int64_t.
Os números negativos são um pouco mais complicados: eles são armazenados em código direto , enquanto int64_t é armazenado em código complementar . Isso significa que, para usar uma comparação inteira, os 63 bits inferiores de um duplo devem ser invertidos (isso resultará em -0. <+0., O que não corresponde ao padrão, mas na prática não apresenta um problema ) A verificação explícita de bits de alta ordem e a ramificação condicional destruiriam todos os benefícios de pular para a comparação de inteiros; mas existe uma maneira mais fácil!
inline int64_t to_int64(double x) {
int64_t a = *(int64_t*)&x;
uint64_t mask = (uint64_t)(a >> 63) >> 1;
return a ^ mask;
}
inline bool is_smaller(double x1, double x2) {
return to_int64(x1) < to_int64(x2);
}
a>>63
preenche todos os 64 bits com cópias do bit de sinal e, em seguida,
>>1
limpa o bit mais significativo.
O blog de Daniel Lemire tem um código ligeiramente diferente (da mesma complexidade computacional), mas minha versão mantém a propriedade útil de
to_int64(0.) == 0