## Float 754 to Hamming

29

2

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


1

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 https://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 – 2017-07-29T15:26:21.930

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 – 2017-07-29T15:28:21.080

2@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 – 2017-07-29T15:30:49.860

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 – 2017-07-29T15:53:14.237

"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 – 2017-08-30T22:41:27.470

@PeterCordes In C++ type punning is undefined behaviour (although I think gcc usually does the Right Thing) – Jerry Jeremiah – 2017-08-30T22:43:04.450

@JerryJeremiah: Type-punning with a union is defined in C99, and in GNU C++ as a GNU extension, so g++, clang++, and ICC all support it. Good point about endianness; it's possible for a machine to have different float endian than integer endian, although AFAIK no modern machines are like that. https://stackoverflow.com/q/2945174/224132. C allows for that. But code-golf answers only have to work on at least one implementation, not every implementation, so working on x86/gcc where double is IEEE binary64 is fine :P

– Peter Cordes – 2017-08-30T22:50:22.320

Type-punning with a pointer-cast happens to work in un-optimized gcc, and sometimes works in optimized code (but is a terrible idea). It always works with gcc -O3 -fno-strict-aliasing. (@JerryJeremiah, I assume you were talking about type-punning the way these answers are doing it). – Peter Cordes – 2017-08-30T22:55:50.317

8

# 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


33

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


2+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 – 2017-07-28T17:14:05.157

2Ew, 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 – 2017-07-29T11:15:09.080

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 – 2017-07-29T13:54:11.507

1

@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 – 2017-07-29T14:03:54.773

2

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 – 2017-07-29T14:06:14.973

Oh actually, the Pyth answer is a whole program. Its chroma-key blend function is the same length (13B) as my x86-64 machine code function. The rest of the bytes are for loading two files, applying the function, and saving a png. – Peter Cordes – 2017-07-30T03:08:10.790

11

# 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 – 2017-07-28T08:58:43.513

@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 – 2017-07-28T09:00:37.107

2Save 9 bytes by shifting the other way: ...;long l=...;l*=2;)s+=l<0;... – Neil – 2017-07-28T09:14:26.930

1This 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 – 2017-07-29T11:31:27.237

1@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 – 2017-07-30T04:38:50.223

@CodyGray I reverted your edit because of your modification to the two lines other than LP64. – Leaky Nun – 2017-07-30T13:38:26.597

-6 bytes for n= rather than return. – S.S. Anne – 2020-02-10T20:44:12.470

8

# 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 – 2017-07-28T17:45:11.097

Or int->float, or any floats at all, for that matter. – user2357112 supports Monica – 2017-07-28T22:27:49.473

8

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

1Input 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 – 2017-07-29T11:37:41.677

1Also, 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 – 2017-07-29T11:38:04.710

1I 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 – 2017-07-29T15:06:19.417

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 – 2017-07-29T15:14:02.217

Yes, many (most?) __builtin_* functions have legacy versions to avoid generating illegal instructions. -march=native uses popcntq only if it's available. – Dennis – 2017-07-29T15:31:56.260

Yeah, of course. I just thought it was a non-obvious fun fact for people who see the highest-voted asm popcnt answer, and then another answer that looks like a C version of the same thing. But it's totally different asm without -mpopcnt. But yeah, that's kinda the point: use the best sequence that the target supports, instead of some pure-C idiom for the compiler to hopefully recognize. I think the only exceptions are things like __builtin_ia32_crc32si or SSE/AVX vector builtins, which aren't declared without the corresponding -m option. https://godbolt.org/g/H78N7S.

– Peter Cordes – 2017-07-29T15:43:48.537

7

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

1

You can eliminate the cast and the loop. See: https://codegolf.stackexchange.com/a/136636/16413

– Nayuki – 2017-07-30T04:12:20.440

6

# 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

2I highly doubt anyone *doesn't want to improve* their answer. – Mr. Xcoder – 2017-07-28T10:32:10.837

1@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. – None – 2017-07-28T10:34:12.123

1I think the input needs to be an integer type and not a real. – ceilingcat – 2017-07-28T10:34:27.143

@ceilingcat. C implicitly converts it to double, but the input is still actualy integer. – None – 2017-07-28T10:34:58.530

3@ThePirateBay I didn't see your comment on my answer and I'm still not seeing it now. – Leaky Nun – 2017-07-28T12:55:45.057

I put my comment and it was staying there for about a hour. In meanwhile I noticed your activity on other questions, so I concluded that you've seen my comment but rejected to improve your answer (probably because you had misunderstood the question that function should take an integer and implicitly convert to double). Also, if I spot a good improvement, what prevents me from posting it as a new answer instead of mentioning the improvement to you? – None – 2017-07-28T14:13:28.087

9The decision to suggest improvements or post your own answer is yours, but 6 minutes is hardly about an hour. – Dennis – 2017-07-28T14:44:24.477

@Dennis. Oh, so much discussion about irrelevant stuff. I've already said, if he really wants rep, I will delete this answer and let him improve his own, no problem. – None – 2017-07-28T14:53:22.837

5

# 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 – 2017-07-28T09:31:19.283

@LeakyNun Thanks I was scratching my head over that for ages. – TheLethalCoder – 2017-07-28T09:34:19.040

Can you use s-=l>>31? – Neil – 2017-07-28T10:01:56.250

@Neil Doesn't appear to work. I assume you mean to replace s+=l<0?1:0? – TheLethalCoder – 2017-07-28T10:05:24.557

My bad; l is a long, so it needs s-=l>>63? – Neil – 2017-07-28T10:11:31.300

@Neil That did the trick, thanks. – TheLethalCoder – 2017-07-28T10:15:31.210

4

## 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 – 2017-07-28T11:20:21.683

@Arnauld I did wonder whether there was a golfier bit twiddle, thanks for finding it! – Neil – 2017-07-28T12:54:23.640

1-3 more if you replace new Float64Array([n]) with Float64Array.of(n) – DocMax – 2017-07-29T00:31:33.243

4

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

171 bytes – ASCII-only – 2017-07-28T10:19:23.140

1Golfing your approach, 76 bytes, I do recommend ASCII-only's approach though – Mr. Xcoder – 2017-07-28T10:20:44.090

@Mr.Xcoder the ! isn't needed since byte order doesn't matter here – ASCII-only – 2017-07-28T10:21:53.677

169 bytes – ASCII-only – 2017-07-28T10:26:46.787

@ASCII-only Pack the unpacked. Thanks :D – Dead Possum – 2017-07-28T10:54:36.777

4

# 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 – 2017-07-30T03:33:03.427

4

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

3

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

3

# 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 – 2017-07-30T13:21:30.660

1

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 – 2017-10-23T13:43:04.740

2

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 – 2017-07-28T10:17:30.913

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 – 2017-07-28T10:22:24.967

@TheLethalCoder it works, but I tried to avoid Linq so I didn't have to add a second using directive. – Charlie – 2017-07-28T10:27:10.787

1When 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 – 2017-07-28T10:29:42.727

@TheLethalCoder, Sum(c=>c&1) is shorter. Or Sum()-768 – Peter Taylor – 2017-07-28T11:31:02.897

@PeterTaylor True, either way it appears to be longer still. – TheLethalCoder – 2017-07-28T11:44:53.167

1

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

1

# Jelly, 19 bytes

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


Try it online!

1

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

1

# Groovy (with Parrot parser), 46 bytes

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


1

# 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