32
\$\begingroup\$

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.

Additional rules

Test cases

22                ->   5
714               ->   6
0                 ->   0
1                 ->  10
4503599627370496  ->   5
4503599627370495  ->  55
1024              ->   3
-1024             ->   4
-4096             ->   5
1000000000        ->  16
-12345678         ->  16
\$\endgroup\$
8
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Jul 29, 2017 at 15:26
  • \$\begingroup\$ 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. \$\endgroup\$ Jul 29, 2017 at 15:28
  • 3
    \$\begingroup\$ @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 \$\endgroup\$
    – Luis Mendo
    Jul 29, 2017 at 15:30
  • \$\begingroup\$ 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 >.< \$\endgroup\$ Jul 29, 2017 at 15:53
  • \$\begingroup\$ "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... \$\endgroup\$ Aug 30, 2017 at 22:41

24 Answers 24

35
\$\begingroup\$

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.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ +1, the right tool for the job! This might be the only time that x86 can legitimately compete with golfing languages, or beat Jelly. :) \$\endgroup\$
    – DJMcMayhem
    Jul 28, 2017 at 17:14
  • 2
    \$\begingroup\$ 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 :/ \$\endgroup\$ Jul 29, 2017 at 11:15
  • \$\begingroup\$ 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. \$\endgroup\$ Jul 29, 2017 at 13:54
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Jul 29, 2017 at 14:03
  • 2
    \$\begingroup\$ 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. \$\endgroup\$ Jul 29, 2017 at 14:06
12
\$\begingroup\$

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!

\$\endgroup\$
7
  • \$\begingroup\$ I knew you would be the first, I just didn't expect the language :-D \$\endgroup\$
    – Luis Mendo
    Jul 28, 2017 at 8:58
  • \$\begingroup\$ @LuisMendo I just thought that it would be convenient in that language... I don't know of other languages that can do this \$\endgroup\$
    – Leaky Nun
    Jul 28, 2017 at 9:00
  • 2
    \$\begingroup\$ Save 9 bytes by shifting the other way: ...;long l=...;l*=2;)s+=l<0;... \$\endgroup\$
    – Neil
    Jul 28, 2017 at 9:14
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Jul 29, 2017 at 11:31
  • 2
    \$\begingroup\$ @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. \$\endgroup\$ Jul 30, 2017 at 4:38
9
\$\begingroup\$

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
\$\endgroup\$
0
9
\$\begingroup\$

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.
\$\endgroup\$
3
  • \$\begingroup\$ n and(…)-(n>0) is a byte shorter, no? \$\endgroup\$
    – Lynn
    Jul 28, 2017 at 17:45
  • \$\begingroup\$ Or int->float, or any floats at all, for that matter. \$\endgroup\$ Jul 28, 2017 at 22:27
  • 1
    \$\begingroup\$ Why the abs? \$\endgroup\$
    – l4m2
    Jun 17, 2020 at 7:55
8
\$\begingroup\$

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!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ 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? \$\endgroup\$ Jul 29, 2017 at 11:37
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Jul 29, 2017 at 11:38
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Dennis
    Jul 29, 2017 at 15:06
  • \$\begingroup\$ 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) \$\endgroup\$ Jul 29, 2017 at 15:14
  • \$\begingroup\$ Yes, many (most?) __builtin_* functions have legacy versions to avoid generating illegal instructions. -march=native uses popcntq only if it's available. \$\endgroup\$
    – Dennis
    Jul 29, 2017 at 15:31
7
\$\begingroup\$

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!

\$\endgroup\$
1
6
\$\begingroup\$

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

\$\endgroup\$
8
  • 2
    \$\begingroup\$ I highly doubt anyone doesn't want to improve their answer. \$\endgroup\$
    – Mr. Xcoder
    Jul 28, 2017 at 10:32
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – user72349
    Jul 28, 2017 at 10:34
  • 1
    \$\begingroup\$ I think the input needs to be an integer type and not a real. \$\endgroup\$
    – ceilingcat
    Jul 28, 2017 at 10:34
  • 3
    \$\begingroup\$ @ThePirateBay I didn't see your comment on my answer and I'm still not seeing it now. \$\endgroup\$
    – Leaky Nun
    Jul 28, 2017 at 12:55
  • 10
    \$\begingroup\$ The decision to suggest improvements or post your own answer is yours, but 6 minutes is hardly about an hour. \$\endgroup\$
    – Dennis
    Jul 28, 2017 at 14:44
5
\$\begingroup\$

C#, 81 70 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));

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

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!

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

x86-64 machine code, 12 bytes for int64_t input

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.

\$\endgroup\$
4
\$\begingroup\$

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

Saved 1 byte thanks to hobbs

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

Try it online!

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

JavaScript (ES6), 81 80 77 76 bytes

f=
n=>new Uint8Array(Float64Array.of(n).buffer).map(g=i=>i&&g(i&i-1,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. Saved 1 byte thanks to @l4m2.

\$\endgroup\$
5
  • \$\begingroup\$ Could you do g(i^i&-i,x++) for -1 byte? \$\endgroup\$
    – Arnauld
    Jul 28, 2017 at 11:20
  • \$\begingroup\$ @Arnauld I did wonder whether there was a golfier bit twiddle, thanks for finding it! \$\endgroup\$
    – Neil
    Jul 28, 2017 at 12:54
  • 1
    \$\begingroup\$ -3 more if you replace new Float64Array([n]) with Float64Array.of(n) \$\endgroup\$
    – DocMax
    Jul 29, 2017 at 0:31
  • \$\begingroup\$ i^i&-i => i&i-1? \$\endgroup\$
    – l4m2
    Jun 16, 2020 at 16:25
  • \$\begingroup\$ @l4m2 Huh, to think that it's been almost 3 years before someone spotted that golf... \$\endgroup\$
    – Neil
    Jun 16, 2020 at 16:47
3
\$\begingroup\$

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.

\$\endgroup\$
0
3
\$\begingroup\$

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))
\$\endgroup\$
2
  • \$\begingroup\$ Nicely done! :-) \$\endgroup\$
    – Leaky Nun
    Jul 30, 2017 at 13:21
  • 2
    \$\begingroup\$ 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) \$\endgroup\$ Oct 23, 2017 at 13:43
3
\$\begingroup\$

JavaScript (Node.js), 7976 bytes

n=>n&&((g=n=>t=n.toString(2))(n)+g(t.length*2-(n<0)+2044)).split`1`.length-2

Try it online!

First answer not relying on cast? At least this is earlier

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ Nice alternative but you need to include the using into your byte count. \$\endgroup\$ Jul 28, 2017 at 10:17
  • \$\begingroup\$ 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. \$\endgroup\$ Jul 28, 2017 at 10:22
  • \$\begingroup\$ @TheLethalCoder it works, but I tried to avoid Linq so I didn't have to add a second using directive. \$\endgroup\$
    – Charlie
    Jul 28, 2017 at 10:27
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Jul 28, 2017 at 10:29
  • \$\begingroup\$ @TheLethalCoder, Sum(c=>c&1) is shorter. Or Sum()-768 \$\endgroup\$ Jul 28, 2017 at 11:31
2
\$\begingroup\$

Jelly, 19 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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.
I'll add an explanation later.

Try it online!

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

\$\endgroup\$
1
\$\begingroup\$

Groovy (with Parrot parser), 46 bytes

f=n->Long.bitCount(Double.doubleToLongBits(n))
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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:

\$\endgroup\$
1
\$\begingroup\$

Husk, 20 bytes

&->0±¹ΣS+ȯḋ+1022Lḋa¹

Try it online! A port of Leaky Nun's Python 3 answer.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 17 bytes

ĀiÄbDgŽ42+b«1¢Id-

Port of @LeakyNun's Python 3 answer, so make sure to upvote him as well!

Try it online or verify all test cases.

Explanation:

Āi                 # If the (implicit) input-integer is NOT 0:
  Ä                #  Take the absolute value of the (implicit) input-integer
   b               #  Convert it to binary
    Dg             #  Duplicate it, then pop and push its length
      Ž42+         #  Add compressed integer 1022 to this length
          b        #  Convert it to binary as well
           «       #  Merge the two binary-strings together
            1¢     #  Count the amount of 1s in this string
              Id   #  Check that the input-integer is non-negative (1 if >=0; 0 if <0)
                -  #  Subtract that from the count
                   #  (after which it is output implicitly as result)
                   # (implicit else: output the implicit input, which is 0)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ž42 is 1022.

\$\endgroup\$
0
\$\begingroup\$

Rust, 27 bytes

|n|n.to_bits().count_ones()

Try it online!

An anonymous function that takes in an f64 and outputs a u32. The to_bits function reinterprets the bits of an f64 into a u64, where I can use the convenient count_ones function to trivialize the problem.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.