3

Given a value x and an integer n (assigned at runtime), I want to print x to exactly n digits after the decimal (after rounding if needed).

print(round(x, n)) works fine for (x,n)=(3.141592, 3) but for (x,n)=(2.5,5), it prints just 2.5, not 2.50000 (5 digits after decimal point).

If I knew n at runtime, say 5, I could do

@printf("%.5f", x)

But @printf being a macro needs n to be known at compile time.

Is this possible using some show magic or something else?

sundar - Remember Monica
  • 6,647
  • 5
  • 40
  • 66

2 Answers2

4

Using the fresh new Format.jl package:

using Format

function foo(x, n)
    f = FormatSpec(".$(n)f")
    pyfmt(f, x)
end

foo(2.5, 5)
gpapini
  • 76
  • 3
3

Unfortunately, for some reason the julia version of @printf / @sprintf do not support the "width" sub-specifier as per the c printf standard (see man 3 printf).

If you're feeling brave, you can rely on the c sprintf which supports the "dynamic width" modifier, to collect a string that you then just print as normal.

A = Vector{UInt8}(100); # initialise array of 100 "chars"
ccall( :sprintf, Int32, (Ptr{UInt8}, Cstring, Int64, Float64), A, "%.*f", 4, 0.1 )
print( unsafe_string(pointer(A)) )    #> 0.1000

Note the asterisk in %.*f, and the extra input 4 serving as the dynamic width modifier.

Tasos Papastylianou
  • 18,605
  • 2
  • 20
  • 44
  • 1
    Ha, I'd never in a million years would have thought of using `ccall` for this. I'll probably never resort to this method, but props to you for creative problem solving! – sundar - Remember Monica Jun 07 '18 at 17:48