Printf with variable number of digits

I am trying to write some code that computes some number up to some precision and prints it with the correct number of digits. I tried the following:

using Printf

function print_number(x, err)
    numofdigits = ceil(Int, -log10(err))
    @printf("%.*f ± %.*f\n", numofdigits, x, numofdigits, err)
end

print_number(3.12345, 0.01)  # Should print 3.12 ± 0.01

but the code produces the error ArgumentError: invalid format string: '%.*f ± %.f', invalid type specifier: '*'.

I wasn’t expecting this, as the @printf documentation explicitly points to the C++ specification of format strings, where the %.*f syntax is supported. Am I missing something, or it is not possible with @printf to do this? And if it is not, what would be a simple workaround?

Don’t use @printf, use format + Format:

julia> using Printf

julia> function print_number(x, err)
           numofdigits = ceil(Int, -log10(err))
           Printf.format(Printf.Format("%.$(numofdigits)f ± %.$(numofdigits)f\n"), x, err)
       end
print_number (generic function with 1 method)

julia> print_number(3.12345, 0.01)  # Should print 3.12 ± 0.01
"3.12 ± 0.01\n"
3 Likes

Thanks! So I understand that the * character is not supported in Julia. Do you think this should be stated somewhere in the documentation?

I’m not familiar with the internals of the Printf module, but it’d appear it doesn’t work, so yes, it may be worth mentioning it in the documentation.

2 Likes

Linking similar post and PR.

1 Like

Thanks! I looked for existing threads in this forum but wasn’t able to find that one. (I could just have looked in the issues of the Printf package, silly of me…)

Most flags that have some dynamic interpretation aren’t supported (we do some length checking to make sure the format object & the number of arguments match for example, to prevent security issues). The general rule of thumb is that if the formatting can be done purely based on a constant format string, it should work. This should definitely be better documented though, instead of just linking to an external ressource.