# Float 754 to Hamming

You will be given as input an integer k in the range from -4503599627370496 (−252) to 4503599627370496 (252). As is well known, integers in this range can be represented exactly as double-precision floating-point values.

You should output the Hamming weight (number of ones) of the encoding of k in binary64 format. This uses 1 bit for the sign, 11 bits for the exponent (encoded with an offset), and 52 for the mantissa; see the above link for details.

As an example, number 22 is represented as

0 10000000011 0110000000000000000000000000000000000000000000000000


Since there are 5 ones, the output is 5.

Note that endianness doesn't affect the result, so you can safely use your machine's actual internal representation of double-precision values to compute the output.

### Test cases

22                ->   5
714               ->   6
0                 ->   0
1                 ->  10
4503599627370496  ->   5
4503599627370495  ->  55
1024              ->   3
-1024             ->   4
-4096             ->   5
1000000000        ->  16
-12345678         ->  16

• Are you intending that functions can accept their inputs already in floating-point binary64 format if they want? Some people (including myself, initially) were interpreting the question as requiring that functions accept inputs as an integer type like C's long. In C, you can argue that the language will convert for you, just like when you call sqrt((int)foo). But there are some x86 machine-code asm answers (like codegolf.stackexchange.com/a/136360/30206 and mine) which were both assuming we had to accept 64-bit integer inputs. Accepting a binary64 value would save 5 bytes. – Peter Cordes Jul 29 '17 at 15:26
• If so, then all that stuff about limited-range is just in case someone wanted to hack up the conversion to a binary64 bit-pattern themselves instead of type-punning? Or for languages without type-punning? Hmm, an interesting challenge might be to add the exponent and mantissa of a binary64 as base2 integers. If you need to handle them separately anyway, it might be worth doing something other than type-pun and loop over all the bits. – Peter Cordes Jul 29 '17 at 15:28
• @PeterCordes Yes, you can input in the form of a a floating-point number. The limited range is to make sure that the floating-point representation is accurate – Luis Mendo Jul 29 '17 at 15:30
• Ok, thanks. I guess you wanted to leave the option of writing a function that takes a long, so you couldn't just say any binary64 double, because not all doubles are integers. But all integer-valued doubles can be converted to long and back, up to the limits of long. (As you point out, the reverse isn't true. You get the nearest representable double, assuming default rounding mode). Anyway, this was a totally valid way to set up the question; I just didn't read it carefully >.< – Peter Cordes Jul 29 '17 at 15:53
• "Note that endianness doesn't affect the result, so you can safely use your machine's actual internal representation of double-precision values to compute the output." unless your machine doesn't use IEEE floating point format... – Jerry Jeremiah Aug 30 '17 at 22:41

# MATL, 5 bytes

3Z%Bz


Try it online!

Exact transliteration of my MATLAB answer. Note that input and output are implicit. -2 bytes thanks to Luis Mendo.

3Z%   % Typecast: changes input (implicitly taken and converted to double) to uint64 without changing underlying bits
B     % Convert integer to array of 1s and 0s
z     % Count nonzero entries


# 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));
}

• +1, the right tool for the job! This might be the only time that x86 can legitimately compete with golfing languages, or beat Jelly. :) – James Jul 28 '17 at 17:14
• Ew, AT&T syntax? You can use objdump -drwC -Mintel to disassemble in Intel syntax. If you had a pointer in a register that you could use to store/reload, you could save bytes with movaps [rsi], xmm0 / popcnt rax, [rsi]. (movaps is only 3 bytes, 2 shorter than movq.) But that doesn't help here, because [rsp-24] takes 2 extra bytes (SIB from using RSP as base, plus disp8). And those extra bytes are needed in both the store and reload. Oh well, I thought I saw a saving, but nope :/ – Peter Cordes Jul 29 '17 at 11:15
• I saved 4 bytes with a custom calling convention. Or still save 2 bytes with the same calling convention as this, by using x87 instructions. – Peter Cordes Jul 29 '17 at 13:54
• @DJMcMayhem: Maybe not the only time. There are still no golfing-language answers on the Extreme Fibonacci challenge (print the first 1000 digits of Fib(1 billion), and my x86 machine code answer (105 bytes fast, or 101 bytes that runs in 5 mins instead of 1 min) is not much larger than some of the other answers, and they're all in languages with extended-precision integers built in. – Peter Cordes Jul 29 '17 at 14:03
• Or a simpler challenge, (and without a performance requirement), chroma-key blending an array of integers. My machine-code answer is half the length of the pyth answer. – Peter Cordes Jul 29 '17 at 14:06

# 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!

• I knew you would be the first, I just didn't expect the language :-D – Luis Mendo Jul 28 '17 at 8:58
• @LuisMendo I just thought that it would be convenient in that language... I don't know of other languages that can do this – Leaky Nun Jul 28 '17 at 9:00
• Save 9 bytes by shifting the other way: ...;long l=...;l*=2;)s+=l<0;... – Neil Jul 28 '17 at 9:14
• This of course requires a C implementation with 64-bit long. It works on x86-64 Linux, but would fail on Windows. I'd suggest saying "gcc with 64-bit long", since gcc runs on many platforms, many of them with different ABIs. – Peter Cordes Jul 29 '17 at 11:31
• @Peter's comment is why I added "LP64" in an edit. I also rearranged the other text in what I thought was a more logical order. I guess you didn't like that change and rolled it back, but LP64 is a standard term that describes the ABI where longs and pointers are 64-bit values (as compared to ILP64, where ints are also 64-bit, or LLP64, as used on Windows where only long longs and pointers are 64-bit and longs are still 32-bit). Maybe I should have added more explanation, or an inline link to the relevant Wikipedia article. – Cody Gray Jul 30 '17 at 4:38

# 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.
• n and(…)-(n>0) is a byte shorter, no? – Lynn Jul 28 '17 at 17:45
• Or int->float, or any floats at all, for that matter. – user2357112 supports Monica Jul 28 '17 at 22:27

# C (gcc), 47 bytes

f(double n){n=__builtin_popcountl(*(long*)&n);}


This isn't portable; it was tested with gcc 7.1.1 on x86_64 running Linux, without compiler flags.

Try it online!

• Input has to be an integer. Or is it ok to let the caller handle that by implicit conversion of long to double at the call site? – Peter Cordes Jul 29 '17 at 11:37
• Also, relying on a fluke of compiler behaviour to happen to leave n in rax with un-optimized code is pretty cheesy. It breaks if you enable -O3, so it's not just gcc in general, it's gcc on x86-64 with 64-bit long with optimization disabled. If you put all those requirements into your answer, I'd upvote. I'd assume there are platforms gcc supports that have 64-bit long but that happen to leave the popcountl result in a register other than the return-value register. – Peter Cordes Jul 29 '17 at 11:38
• I took integer in the mathematical sense. I've added the specs of my test environments, as I'm not sure that gcc, x86-64, and 64-bit longs are enough. That said, at least on x86, return-less functions work with gcc (and tcc) more often than not. – Dennis Jul 29 '17 at 15:06
• Yeah, I was just re-reading the question, and I agree that accepting the arg as a double should be fine. It doesn't say anything about requiring the function to accept it in base2 format. And yes, different versions of gcc could emit different code, so that's important, too. (Fun fact: without -mpopcnt, gcc won't use the popcnt insn, and will emit a sequence of instructions to emulate it. Some architectures don't have a popcnt instruction at all, so __builtin_popcountl always has to use some sequence of insns) – Peter Cordes Jul 29 '17 at 15:14
• Yes, many (most?) __builtin_* functions have legacy versions to avoid generating illegal instructions. -march=native uses popcntq only if it's available. – Dennis Jul 29 '17 at 15:31

# Java (OpenJDK 8), 92 bytes

int f(long n){int s=0;for(n=Double.doubleToLongBits((double)n);n!=0;n>>>=1)s+=n&1;return s;}


Try it online!

# C (gcc), 63 bytes

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


This solution is based on @LeakyNun's answer, but because he doesn't want to improve his own answer, I'm posting here more golfed version.

Try it online

• I highly doubt anyone doesn't want to improve their answer. – Mr. Xcoder Jul 28 '17 at 10:32
• @Mr.Xcoder. Ok, I'll keep this here until he edit his own answer. If he doesn't want to edit, this will stay here. I posted this improvement as a comment on his answer and he rejected it. – user72349 Jul 28 '17 at 10:34
• I think the input needs to be an integer type and not a real. – ceilingcat Jul 28 '17 at 10:34
• @ThePirateBay I didn't see your comment on my answer and I'm still not seeing it now. – Leaky Nun Jul 28 '17 at 12:55
• The decision to suggest improvements or post your own answer is yours, but 6 minutes is hardly about an hour. – Dennis Jul 28 '17 at 14:44

# C#, 8170 68 bytes

d=>{unsafe{long l=*(long*)&d,s=0;for(;l!=0;l*=2)s-=l>>63;return s;}}


Save 11 bytes thanks to @Leaky Nun.
Saved 2 bytes thanks to @Neil.

Try it online! Uses System.BitConverter.DoubleToInt64Bits instead of the unsafe code as I couldn't get TIO to work with it.

Full/Formatted Version:

namespace System
{
class P
{
static void Main()
{
Func<double, long> f = d =>
{
unsafe
{
long l = *(long*)&d, s = 0;

for (; l != 0; l *= 2)
s -= l >> 63;
return s;
}
};

Console.WriteLine(f(22));
Console.WriteLine(f(714));
Console.WriteLine(f(0));
Console.WriteLine(f(1));
Console.WriteLine(f(4503599627370496));
Console.WriteLine(f(4503599627370495));
Console.WriteLine(f(1024));
Console.WriteLine(f(-1024));
Console.WriteLine(f(-4096));
Console.WriteLine(f(1000000000));
Console.WriteLine(f(-12345678));

}
}
}

• for(;l!=0;l*=2) and you won't need the ternary – Leaky Nun Jul 28 '17 at 9:31
• @LeakyNun Thanks I was scratching my head over that for ages. – TheLethalCoder Jul 28 '17 at 9:34
• Can you use s-=l>>31? – Neil Jul 28 '17 at 10:01
• @Neil Doesn't appear to work. I assume you mean to replace s+=l<0?1:0? – TheLethalCoder Jul 28 '17 at 10:05
• My bad; l is a long, so it needs s-=l>>63? – Neil Jul 28 '17 at 10:11

# Python 2, 69 bytes

-12 bytes, thanks to @ASCII-only

lambda n:bin(*unpack('Q',pack('d',n))).count('1')
from struct import*


Try it online!

• 71 bytes – ASCII-only Jul 28 '17 at 10:19
• Golfing your approach, 76 bytes, I do recommend ASCII-only's approach though – Mr. Xcoder Jul 28 '17 at 10:20
• @Mr.Xcoder the ! isn't needed since byte order doesn't matter here – ASCII-only Jul 28 '17 at 10:21
• 69 bytes – ASCII-only Jul 28 '17 at 10:26
• @ASCII-only Pack the unpacked. Thanks :D – Dead Possum Jul 28 '17 at 10:54

## JavaScript (ES6), 8180 77 bytes

f=
n=>new Uint8Array(Float64Array.of(n).buffer).map(g=i=>i&&g(i^i&-i,x++),x=0)|x
<input oninput=o.textContent=f(this.value)><pre id=o>0

Edit: Saved 1 byte thanks to @Arnauld. Saved 3 bytes thanks to @DocMax.

• Could you do g(i^i&-i,x++) for -1 byte? – Arnauld Jul 28 '17 at 11:20
• @Arnauld I did wonder whether there was a golfier bit twiddle, thanks for finding it! – Neil Jul 28 '17 at 12:54
• -3 more if you replace new Float64Array([n]) with Float64Array.of(n) – DocMax Jul 29 '17 at 0:31

# 6 bytes for double input

Requires the popcnt ISA extension (CPUID.01H:ECX.POPCNT [Bit 23] = 1).

(Or 13 bytes if modifying the arg in-place requires writing all 64-bits, instead of leaving garbage in the upper 32. I think it's reasonable to argue that the caller would probably only want to load the low 32b anyway, and x86 zero-extends from 32 to 64 implicitly with every 32-bit operation. Still, it does stop the caller from doing add rbx, [rdi] or something.)

x87 instructions are shorter than the more obvious SSE2 cvtsi2sd/movq (used in @ceilingcat's answer), and a [reg] addressing mode is the same size as a reg: just a mod/rm byte.

The trick was to come up with a way to have the value passed in memory, without needing too many bytes for addressing modes. (e.g. passing on the stack isn't that great.) Fortunately, the rules allow read/write args, or separate output args, so I can just get the caller to pass me a pointer to memory I'm allowed to write.

Callable from C with the signature: void popc_double(int64_t *in_out); Only the low 32b of the result is valid, which is maybe weird for C but natural for asm. (Fixing this requires a REX prefix on the final store (mov [rdi], rax), so one more byte.) On Windows, change rdi to rdx, since Windows doesn't use the x86-64 System V ABI.

NASM listing. The TIO link has the source code without the disassembly.

  1  addr    machine      global popcnt_double_outarg
2          code         popcnt_double_outarg:
3                           ;; normal x86-64 ABI, or x32: void pcd(int64_t *in_out)
4 00000000 DF2F             fild qword  [rdi]    ; int64_t -> st0
5 00000002 DD1F             fstp qword  [rdi]    ; store binary64, using retval as scratch space.
6 00000004 F3480FB807       popcnt rax, [rdi]
7 00000009 8907             mov    [rdi], eax    ; update only the low 32b of the in/out arg
8 0000000B C3               ret
# ends at 0x0C = 12 bytes


Try it online! Includes a _start test program that passes it a value and exits with exit status = popcnt return value. (Open the "debug" tab to see it.)

Passing separate input/output pointers would also work (rdi and rsi in the x86-64 SystemV ABI), but then we can't reasonably destroy the 64-bit input or as easily justify needing a 64-bit output buffer while only writing the low 32b.

If we do want to argue that we can take a pointer to the input integer and destroy it, while returning output in rax, then simply omit the mov [rdi], eax from popcnt_double_outarg, bringing it down to 10 bytes.

## Alternative without silly calling-convention tricks, 14 bytes

use the stack as scratch space, with push to get it there. Use push/pop to copy registers in 2 bytes instead of 3 for mov rdi, rsp. ([rsp] always needs a SIB byte, so it's worth spending 2 bytes to copy rsp before three instructions that use it.)

Call from C with this signature: int popcnt_double_push(int64_t);

 11                               global popcnt_double_push
12                               popcnt_double_push:
13 00000040 57                       push   rdi         ; put the input arg on the stack (still in binary integer format)
14 00000041 54                       push   rsp         ; pushes the old value (rsp updates after the store).
15 00000042 5A                       pop    rdx         ; mov      rdx, rsp
16 00000043 DF2A                     fild   qword [rdx]
17 00000045 DD1A                     fstp   qword [rdx]
18 00000047 F3480FB802               popcnt rax,  [rdx]
19 0000004C 5F                       pop    rdi         ; rebalance the stack
20 0000004D C3                       ret
next byte is 0x4E, so size = 14 bytes.


# Accepting input in double format

The question just says it's an integer in a certain range, not that it has to be in a base2 binary integer representation. Accepting double input means there's no point in using x87 anymore. (Unless you use a custom calling convention where doubles are passed in x87 registers. Then store to the red-zone below the stack, and popcnt from there.)

11 bytes:

 57 00000110 66480F7EC0               movq    rax, xmm0
58 00000115 F3480FB8C0               popcnt  rax, rax
59 0000011A C3                       ret


But we can use the same pass-by-reference trick as before to make a 6-byte version: int pcd(const double&d);

 58 00000110 F3480FB807               popcnt  rax, [rdi]
59 00000115 C3                       ret


6 bytes.

# Perl 5, 33 32 + 1 (-p) = 34 33 bytes

Saved 1 byte thanks to hobbs

$_=(unpack"B*",pack d,$_)=~y/1//


Try it online!

• You can save 1 byte by making d a bareword (pack d,$_ instead of pack"d",$_) – hobbs Jul 30 '17 at 3:33

## MATLAB, 36 bytes

@(n)nnz(de2bi(typecast(n,'uint64')))


Using the fact that de2bi is not only shorter than dec2bin, but also provides a result in ones and zeroes rather than ASCII 48, 49.

# Java (64, 61, 41 bytes)

Completely straightforward using the standard library (Java SE 5+):

int f(long n){return Long.bitCount(Double.doubleToLongBits(n));}

Contribution by Kevin Cruijssen (Java SE 5+):

int f(Long n){return n.bitCount(Double.doubleToLongBits(n));}


Contribution by Kevin Cruijssen (Java SE 8+, lambda function):

n->n.bitCount(Double.doubleToLongBits(n))

• Nicely done! :-) – Leaky Nun Jul 30 '17 at 13:21
• Nice answer, +1 from me. You can golf three bytes by taking the parameter as Long n and use n.bitCount(...) instead of Long.bitCount(...). In addition, if you use Java 8+, you can golf it to n->n.bitCount(Double.doubleToLongBits(n)) (41 bytes) – Kevin Cruijssen Oct 23 '17 at 13:43

Just to try a different, safer-than-TheLethalCoder's approach, I came up with this (it's a pity C# has such long method names):

# C# (.NET Core), 76+13 bytes

d=>Convert.ToString(BitConverter.DoubleToInt64Bits(d),2).Split('1').Length-1


Try it online!

Byte count includes 13 bytes for using System;. First I need to convert the double to a long that has the same binary representation, then I can convert it to a binary string, and then I count the 1s just by splitting the string and counting the substrings minus 1.

• Nice alternative but you need to include the using into your byte count. – TheLethalCoder Jul 28 '17 at 10:17
• Use Linq for 95 bytes only a few more: namespace System.Linq;{d=>Convert.ToString(BitConverter.DoubleToInt64Bits(d),2).Count(c=>c>48)}. Though I haven't tested it, it should work. – TheLethalCoder Jul 28 '17 at 10:22
• @TheLethalCoder it works, but I tried to avoid Linq so I didn't have to add a second using directive. – Charlie Jul 28 '17 at 10:27
• When you add the second that's when namespaces come in handy. But yeah in this case avoiding Linq was slightly cheaper. Just wanted to comment with it's approach in case you had any ideas on how to shorten it to save you bytes. – TheLethalCoder Jul 28 '17 at 10:29
• @TheLethalCoder, Sum(c=>c&1) is shorter. Or Sum()-768 – Peter Taylor Jul 28 '17 at 11:31

# Jelly, 19 bytes

AB©L+⁽¡ßB;®ċ1_>0\$a@


Try it online!

# dc, 79 bytes

[pq]su[-1r]st0dsb?dd0=u0>tsa[1+]ss[la2%1=slb1+sblad2/sa1<r]dsrxlb1022+sa0lrx+1-


Output is left on top of the stack.

Try it online!

Note that negative numbers are preceded by _, not -.

# Groovy (with Parrot parser), 46 bytes

f=n->Long.bitCount(Double.doubleToLongBits(n))


# C, 67 bytes

int i;g(char*v){int j=v[i/8]&1<<i%8;return!!j+(++i<64?g(v):(i=0));}


control code and results

#define R     return
#define u32 unsigned
#define F        for
#define P     printf

int main()
{/*           5   6 0 10                5               55    3      4       16*/
double v[]={22,714,0,1 ,4503599627370496,4503599627370495,1024, -1024, -12345678};
int i;

F(i=0;i<9;++i)
P("%f = %d\n", v[i], g(&v[i]));
R 0;
}

>tri4
22.000000 = 5
714.000000 = 6
0.000000 = 0
1.000000 = 10
4503599627370496.000000 = 5
4503599627370495.000000 = 55
1024.000000 = 3
-1024.000000 = 4
-12345678.000000 = 16


# Erlang 55 bytes

fun(X)->length([Y||<<Y:1>><=<<X:64/float>>,Y=:=1])end.


An anonymous function that counts all the 1s in a number encoded as a 64 bit float.

references: