Float 754 to Hamming

x86_64 machine language (Linux), 16 bytes

0:       f2 48 0f 2a c7          cvtsi2sd %rdi,  %xmm0
5:       66 48 0f 7e c0          movq     %xmm0, %rax
a:       f3 48 0f b8 c0          popcnt   %rax,  %rax
f:       c3                      retq

Accepts a single 64-bit integer parameter in RDI, converts it to a floating-point value in XMM0, stores those bits back in RAX, and then computes the hamming weight of RAX, leaving the result in RAX so it can be returned to the caller.

Requires a processor that supports the POPCNT instruction, which would be Intel Nehalem, AMD Barcelona, and later microarchitectures.

To Try it online!, compile and run the following C program:

#include<stdio.h>
const char g[]="\xF2\x48\x0F\x2A\xC7\x66\x48\x0F\x7E\xC0\xF3\x48\x0F\xB8\xC0\xC3";
#define f(x) ((int(*)(long))g)(x)

int main(int a){
  printf("%d\n",f(22));
  printf("%d\n",f(714));
  printf("%d\n",f(0));
  printf("%d\n",f(1));
  printf("%d\n",f(4503599627370496L));
  printf("%d\n",f(4503599627370495L));
  printf("%d\n",f(1024));
  printf("%d\n",f(-1024));
  printf("%d\n",f(-4096));
  printf("%d\n",f(1000000000));
  printf("%d\n",f(-12345678));
}

Edit: Fixed segfault in TIO link.


C (gcc), 82 68 bytes

9 bytes thanks to Neil.

evil floating point bit level hacking

s;f(long n){double d=n;n=*(long*)&d;for(s=0;n;n*=2)s+=n<0;return s;}

Try it online!


Python 3, 72 71 bytes

1 byte thanks to Lynn.

lambda n:n and(bin(1020+len(bin(abs(n))))+bin(abs(n))).count('1')-(n>0)

Try it online!

Explanation

The binary64 format consists of three components:

  • the first bit is the sign bit, which is 1 if the number is negative
  • the next 11 bits store the exponent with 1023 added
  • the next 52 bits store the significand, or the mantissa.