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.