The format is a 64 bit value x representing a IEEE-754 double-precision binary floating-point number (a.k.a "a double"). x is assumed to represent a real number (not a NaN or Infinity).


The goal is to print/output the shortest string containing a decimal representation for which x is the closest IEEE 754 representation. Scientific notation is allowed. You can choose whether or not to allow a missing 0 in front of the ".".

x = 0x4000CCCCCCCCCCCD could be represented as "2.10000000000000008881784197001" but also as "2.1", which is much shorter. x = 0x3DDB7CDFD9D7BDBB can be represented as "1e-10" which is much shorter than alternative representation "1.0000000000000000364321973155E-10"


In addition to being correct, the program must run in a reasonable amount of time on a modern CPU, ruling out some forms of exhaustive search.

This being code-golf entries should be judged by concision, but voters should feel free to attribute points based on a discretionary judgment of elegance, and efficiency.

A few test cases

In these test cases, I represent the input as an hexadecimal number to make it clear that a IEEE 754 double 64 is passed. You can pass it as a double if the language supports it, or as a 64 bit integer, at your convenience.

f(0x4000CCCCCCCCCCCD) == "2.1" 
f(0x3DDB7CDFD9D7BDBB) == "1e-10"
f(0x40934A456D5CFAAD) == "1234.5678" // N.B. not 1.2345678e3
f(0x3FEFFFFFFAA19C47) == "0.99999999"
f(0xC088A8CF13CEE9DD) == "-789.101112"`
  • \$\begingroup\$ If by "C will parse" you're talking about C compilers, the standard says that "the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner." If you're talking about scanf there is still implementation-specific behaviour with regards to rounding. To make this question answerable, I think it needs to be rewritten to talk not about C's parsing but about the string-to-double conversion of the language used in the answer. \$\endgroup\$ Commented Dec 2, 2014 at 12:49
  • \$\begingroup\$ The cleanest way of expressing it is probably to require that the answer be a function (whose length is counted for the score) and also include a test framework (length not counted) which demonstrates that the string returned by the function round-trips to the original value. \$\endgroup\$ Commented Dec 2, 2014 at 12:51
  • \$\begingroup\$ OK I'll edit in a few hours with a few test cases. The requirement isn't compiler specific, it's a standard. But I'll replace with what the standard actually says... \$\endgroup\$
    – Arthur B
    Commented Dec 2, 2014 at 13:10
  • 1
    \$\begingroup\$ Can I submit an entry for Python 3.1 with f=str? Because Python will always choose the shortest representation. \$\endgroup\$
    – kennytm
    Commented Dec 2, 2014 at 15:51
  • 2
    \$\begingroup\$ I don't think this challenge is worthwhile unless solutions that are effectively calls to printf are disqualified. \$\endgroup\$
    – hobbs
    Commented Dec 6, 2014 at 7:17

3 Answers 3


C - 47 45 characters

Counting just the function f, and not including #includes and main.

In C, the %g fprintf specifier will always choose the shortest format. Add a precision specifier equal to the usual maximum precision of double and a bit of casting hocus-pocus to coerce int64 to double and Bob's your uncle.

#include <assert.h>
#include <stdint.h>
#include <stdio.h>

// The following line is what I'm counting...
f(int64_t u){printf("%.14g\n",*(double*)&u);}

int main()
    assert(sizeof(int64_t) == sizeof(double));


    return 0;

Output is as per specs:


Summary: C rocks!

  • 1
    \$\begingroup\$ You can save a character by using uint64_t in place of long long, or even 2 characters if you use int64_t. \$\endgroup\$
    – Paul R
    Commented Dec 2, 2014 at 17:32
  • \$\begingroup\$ @PaulR - Thank you, will try that out! \$\endgroup\$
    – user15259
    Commented Dec 2, 2014 at 18:19
  • \$\begingroup\$ You may pass the test set, but not the general requirement. %g picks the shortest of %f or %e, but %f will not always reproduce all the digits necessary to represent the number. \$\endgroup\$
    – Arthur B
    Commented Dec 15, 2014 at 20:38
  • \$\begingroup\$ @ArthurB - %14g will propagate the 14 to %f or %e. /YR \$\endgroup\$
    – user15259
    Commented Dec 15, 2014 at 21:23
  • 1
    \$\begingroup\$ Maximum (round-tripping) precision of double is 15 decimal places, and to print unambiguous representation of every given binary number you need up to 17. \$\endgroup\$
    – Ruslan
    Commented Jan 26, 2017 at 19:19

Common Lisp - 138 bytes

 (ql:quickload'(ieee-floats cl-ppcre))(lambda(x)(#1=ppcre:regex-replace"e0$"(#1#"\\.?d"(format()"~a"(ieee-floats:decode-float64 x))"e")""))

(138 = 101 for the actual function + 37 for quickload'ing libraries)


The default representation of floating-points in CL is already quite close to the requested output. However, there are some discrepancies. For example, double-precisions numbers are written with a d exponent character (e.g., 2.10d0). That is why I modify the output of the formatted string with regexes:

(ql:quickload '(ieee-floats cl-ppcre))
(lambda (x)
  (cl-ppcre:regex-replace  ; remove "e0" at end of string
     (cl-ppcre:regex-replace ; change ".d" and "d" to "e"
       (format nil "~a" (ieee-floats:decode-float64 x))


;; NB: * is set by the REPL to the last returned value. 
;; Here, we store the previously defined lambda:
(defparameter *fun* *) 

;; Test cases
(defparameter *sample*

;; Default representation
(mapcar #'ieee-floats:decode-float64 *sample*)
=> (2.1d0 1.d-10 1234.5678d0 0.99999999d0 -789.101112d0)

;; Custom conversion
(mapcar *fun* *sample*)
=> ("2.1" "1e-10" "1234.5678" "0.99999999" "-789.101112")


Here, we convert the printed representations back to IEEE-754 doubles.

;; read values as double-precision numbers
(let ((*read-default-float-format* 'double-float))
  (mapcar #'read-from-string *))
=> (2.1 1.e-10 1234.5678 0.99999999 -789.101112)

;; Encode
(mapcar #'ieee-floats:encode-float64 *)
=> (4611911198408756429 4457293557087583675 4653144502051863213 4607182418709945415 13873524259458836957)

;; Check
(equal * *sample*)
=> T

Julia, 20 characters


Function to test the results for correctness:

function decrep()
    tests=[0x4000CCCCCCCCCCCD 0x3DDB7CDFD9D7BDBB 0x40934A456D5CFAAD 0x3FEFFFFFFAA19C47 0xC088A8CF13CEE9DD]
    results=[2.1 1e-10 1234.5678 0.99999999 -789.101112]

    for i=1:length(tests)
        println("input   : $(hex(tests[i]))")
        println("result  : $(r(tests[i]))")
        println("expected: $(results[i])")
        println("$(r(tests[i]) == results[i])")

Executing the test function:

julia> decrep()
input   : 4000cccccccccccd
result  : 2.1
expected: 2.1
input   : 3ddb7cdfd9d7bdbb
result  : 1.0e-10
expected: 1.0e-10
input   : 40934a456d5cfaad
result  : 1234.5678
expected: 1234.5678
input   : 3feffffffaa19c47
result  : 0.99999999
expected: 0.99999999
input   : c088a8cf13cee9dd
result  : -789.101112
expected: -789.101112

If the output absolutely has to be a string, then the solution would be:


with 28 characters.

julia> h=0x4000cccccccccccd

julia> s(h)=string(hex2num(hex(h)))
s (generic function with 1 method)

julia> s(h)

Summary: Julia rocks, too ;)


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.