Formatting comma thousands separator

659 views
Skip to first unread message

Greg Plowman

unread,
Mar 13, 2016, 10:50:39 PM3/13/16
to julia-users
I am trying to find an easy way to format numbers with thousands separators.
It seems the package Formatting can be used for this.

However, I can't seem to get the "python-style" format specifier working.
Below the FormatSpec is correctly created with the field tsep = true, but it appears to have no effect when printing using printfmt.

julia> fspec = FormatSpec(",d")
Formatting.FormatSpec
  cls   = i
  typ   = d
  fill  =
  align = >
  sign  = -
  width = -1
  prec  = -1
  ipre  = false
  zpad  = false
  tsep  = true

julia> printfmt(fspec, 10^9)
1000000000


Similarly for FormatExpr ...

fexpr = FormatExpr("{:,d}")
printfmt(fexpr, 10^9)
1000000000

Am I doing something wrong? Or is this not yet implemented?


I do realise I can use sprint1 with println or @printf, but I was looking to use something more "inline".

@printf("x = %s\n", sprintf1("%'i", x))

Tom Breloff

unread,
Mar 14, 2016, 8:41:37 AM3/14/16
to julia...@googlegroups.com
Also check out https://github.com/ScottPJones/StringUtils.jl, which is an extension of Formatting. 

Scott Jones

unread,
Mar 14, 2016, 9:17:13 PM3/14/16
to julia-users
Thanks Tom!

In order to do this with my package (which uses Tom's nice PR on top of the Formatting package), you could do the following:

val = 123456789
fmt_default
!(Integer, :commas)
println
(u"This is a lot of money: $\%(val)")

(note that $ does not need to be quoted, because I use Swift-style interpolation, i.e. "\(expr)" )

If you don't want all Integers to be output with commas, you can also simply do:
println(u"Let's output with commas: \%(val, :commas)")

I haven't integrated the Python style formatting into my string literals, I think will need to change the syntax I added for LaTex names, from u"\{dagger}", to something else, such as:
u"\$dagger$" or u"\<dagger>", for example, so that I can use \{...} for Python-style formatting.

Thinking about commas, I'd really like it to actually be able to handle different separators, such as ' or _ (which Julia allows for numeric literals), or even, based on locale, to be able to select using , for the decimal point and . for the thousands separator, as they do in Europe.

I wrote this package for my own convenience, because I never liked having the frequently used character $ to indicate interpolation (I know it also causes problems for LaTex users), nor using C style printf macros,
but I hope that it may be useful for other Julia developers (and I'd really like input on how to improve it, in the string literal syntax, in the formatting features, and in the julia code implementing it as well.

Note: since this is not a registered package (hopefully, one day it can be), you'll need to clone it from my repo to use it.

Hope this helps!

Greg Plowman

unread,
Mar 15, 2016, 4:10:03 AM3/15/16
to julia-users
Thanks Tom & Scott.

StringUtils looks quite useful. I'll need to study it a bit more.


For thousands separators, it seems there are many options in fact.

x = 10^9

using Formatting

s
= fmt(",d", x)            # python-style format spec (single value)
s
= format("{:,d}", x)      # python-style form expression (multiple values)
s
= sprintf1("%'d", x)      # c-style
s
= format(x, commas=true)  # keyword arguments

using StringUtils
s
= u"\%(x, :commas)"

(But note the python-style versions don't work)

Then I can print with something like:

println("x = $s")
println
("x = ", s)
@printf("x = %s\n", s)

Or directly with printfmt(), or directly as you described above.

For my purpose I'm using println("x = ", format(x, comma=true))

Although for more complex cases it would be nice if I could write  @printf("x = %'d\n", x")


#########################################################

Also Scott, I noted that in your package that you renamed fmt to cfmt.
Is the "c" in "cfmt" to represent c-style formatting? If so then I think it should be pyfmt for python-style formatting.

Since there are many "styles" emerging for formatting, would it be worth considering names to reflect the style?

cfmt = sprintf1
format (with keyword arguments)
pyfmt = fmt

Scott Jones

unread,
Mar 15, 2016, 11:07:52 PM3/15/16
to julia-users


On Tuesday, March 15, 2016 at 4:10:03 AM UTC-4, Greg Plowman wrote:
Thanks Tom & Scott.

StringUtils looks quite useful. I'll need to study it a bit more.

Thanks!  If you do start using it, please let me know how I can improve it!

About the renaming fmt to cfmt, that was done as part of Tom's PR: https://github.com/JuliaLang/Formatting.jl/pull/10
For Python style format strings, I agree that pyfmt makes sense.  Tom, what do you think?
Feel free to submit issues and/or PRs for any ideas you have like this!

I incorporated Tom's work (with his kind permission!), and the rest of the Formatting.jl package, so as not to reinvent the wheel.
Currently, those parts are identical to the code in the PR.  I'm going to merge in any updates done to Formatting.jl, and try to fix other
issues as I come across them. (there do seem to be a number of places where it doesn't really act like C formatting, for example with things like "%-10s" vs. "%10s",
which should left justify and right justify respectively in a field of 10 characters)
(I'd submit PRs to Formatting.jl, however that's not possible currently, which is another reason I needed to incorporate the code from Formatting.jl instead of just requiring it for the package).

Note: with StringUtils.jl, you can also use a more C-style syntax (but I don't have support for the non-standard ' flag yet, i.e. str = "foo" ; println(u"C-style padding: \%10s(str) \\%8.4f(pi)")

Scott Jones

unread,
Mar 23, 2016, 10:40:42 AM3/23/16
to julia-users
I've now updated things some more, so that there are different functions for different styles: cfmt, pyfmt, fmt, and format.
Also, the cfmt now works much better, you can get your commas, with left or right justification:

julia> u"\%-10.4f(1.234234)"

"1.2342    "

julia> u"\%20'.2f(1234234.234234)"

"          1,234,234.23"


I also added the full set of Unicode character names (i.e. u"\N{dagger}") as well as HTML names (for example: u"\&Aacute;")

Hope you like!


On Tuesday, March 15, 2016 at 4:10:03 AM UTC-4, Greg Plowman wrote:
Reply all
Reply to author
Forward
0 new messages