How to separate three digits of numbers

Hello friends, how can I separate three digits of numbers ?
for example
15252 => 15,252
5444785 => 5,444,785
123 => 123

Thanks

Hello and welcome,

You can separate like this in your code…

15_252
5_444_785
123

# example
iex(1)> 123_234 * 5_300
653140200

But it’s different if You want to render those number on a web page :slight_smile:

I meant the output :slight_smile:

You might use this package…

2 Likes

If you don’t want to use an external package here is an idea:

You can compute the modulo remainder of an integer division of a power of 10 (10, 100, 1000, 10^4, …) to get an amount of digits of a number, for example:

iex> Integer.mod(15252, 10)
2
iex> Integer.mod(15252, 100)
52
iex> Integer.mod(15252, 1000)
252  # what you are looking for the right side

For the left part you need more steps but is equaly easy:

iex> 15252 - Integer.mod(15252, 1000)
15000

so:

iex> 15252 - Integer.mod(15252, 1000) |> Integer.floor_div(1000) 
15

Finally, convert these numbers into strings and concatenate the strings with the comma.

1 Like

Or you can play with charlists and strings, like:

iex> number = 15252
15252
iex> [units, tens, hundreds | reversed_tail] =  Integer.to_charlist(number) |> Enum.reverse()
'25251'
iex> Enum.reverse(reversed_tail) ++ [','] ++ [hundreds, tens, units] |> List.to_string()
"15,252"
1 Like

with num being a charlist

def fmt(num) do
    {h, t} = Enum.split(num, rem(length(num), 3))    
    t = t |> Enum.chunk_every(3) |> Enum.join(",")
    case {h, t} do
       {'', _} -> t
       {_, ""} -> "#{h}"
       _ -> "#{h}," <> t
    end
end
2 Likes

This is amazing
I thank all my friends

1 Like

Just noting that not all cultures group digits in groups of 3 (in India the first group is 2 digits, the others are 3 for example) and many countries don’t use the , as a grouping symbol (for example France uses a space, Germany uses a .). Similar considerations for the decimal separator too. number is great if you know the symbols and the grouping is regular. ex_cldr_numbers will format appropriately based on a locale (I am the author).

13 Likes

Yes, that’s right, thank you

+1 for ex_cldr_numbers

I like @eliottramirez solution because it is using elegant recursion. Here is my more sequential approach:

n = 1234567890
"#{n}" 
|> to_charlist()                  # prepare data
|> Enum.reverse()                 # reverse the entire string
|> Enum.chunk_every(3)            # split in groups of 3
|> Enum.map( & Enum.reverse(&1) ) # reverse each group
|> Enum.reverse()                 # reverse the entire thing
|> Enum.join(",")                 # join with commas
"1,234,567,890"

This one is longer and less elegant
but you may implement 3 and , as configurable.

Anyhow, my advise, when it comes to real life production, also is to use a complete solution from a package as mentioned here already.

2 Likes

You can squash "#{n}" |> to_charlist() into n |> to_charlist() or even use n |> Integer.to_charlist() to avoid dynamic dispatch penalty as you know that n is integer.

3 Likes