How to format the number exactly in Elixir?

What is the most direct and efficient way to do this in Elixir?

Starting number: 123.101

Ending number: 123.101000 # Adding 3 digits to the precision of a float.

Starting number: 123

Ending number: 123.000 # Adding 3 digits to the precision of an integer.

Starting number: 123.101

Ending number: 123.1 # removing precision

Starting number: 123.000

Ending number: 123 # removing precision
+6
source share
5 answers

Just want to provide an alternative to Sobert's excellent answer.

You can also use: erlang.float_to_binary / 2

ex.

iex(5)> :erlang.float_to_binary(123.101, [decimals: 6])
"123.101000"

iex(6)> :erlang.float_to_binary(123.0, [decimals: 3])
"123.000"

iex(7)> :erlang.float_to_binary(123.101, [decimals: 1])
"123.1"

iex(8)> :erlang.float_to_binary(123.000, [decimals: 0])
"123"
+14
source

There is nothing similar in the Elixir standard library, but I can use :io_lib.format/2from Erlang to print a float with a certain number of digits after the dot:

iex(1)> :io_lib.format("~.3f", [123.101])
['123.101']
iex(2)> :io_lib.format("~.6f", [123.101])
['123.101000']
iex(3)> :io_lib.format("~.3f", [123.0])
['123.000']
iex(4)> :io_lib.format("~.6f", [123.0])
['123.000000']

The return value is one iolistthat can be converted to binary using IO.iodata_to_binary/1if necessary (many functions that accept a binary can take directly iolist, for example IO.puts/1):

iex(5)> :io_lib.format("~.6f", [123.0]) |> IO.iodata_to_binary
"123.000000"

~.0f , trunc/1:

iex(6)> trunc(123.123)
123
+4

. -, . -, !

:

Starting number: 123.101

Ending number: 123.101000 # Adding 3 digits to the precision of a float.

iex> 123.101 |> Decimal.new() |> Decimal.round(6)
#Decimal<123.101000>


Starting number: 123

Ending number: 123.000 # Adding 3 digits to the precision of an integer.

iex> 123 |> Decimal.new() |> Decimal.round(3)    
#Decimal<123.000>


Starting number: 123.101

Ending number: 123.1 # removing precision

iex> 123.101 |> Decimal.new() |> Decimal.round(1)
#Decimal<123.1>


Starting number: 123.000

Ending number: 123 # removing precision

iex> 123.000 |> Decimal.new() |> Decimal.round(0)
#Decimal<123>

Decimal, , , . float, ..

iex> 123.101 |> Decimal.new() |> Decimal.round(6) |> Decimal.to_string()
"123.101000"

iex> 123.101 |> Decimal.new() |> Decimal.round(6) |> Decimal.to_float() 
123.101

iex> 123.101 |> Decimal.new() |> Decimal.round(0) |> Decimal.to_integer()
123

, Decimal, - , . Decimal.mult(num1, num2), Decimal.div(num1, num2) .. Decimal !

+2

decimal

iex(6)> 123 |> Decimal.new() |> Decimal.round(3) |> Decimal.to_string()
"123.000"

.

+1

, :

defmodule NumFmt do
  def format(value, pos, round? \\ true)
  def format(value, pos, _) when is_integer(value),
    do: format(Integer.to_string(value), pos)
  def format(value, pos, round?) when is_float(value),
    do: format(Float
               |> apply((if round?, do: :round, else: :floor), [value, pos]) 
               |> Float.to_string, pos)
  def format(value, 0, _) when is_binary(value),
    do: with [i | _] <- String.split(value, "."), do: i
  def format(value, pos, round?) when is_binary(value) do
    case String.split(value, ".") do
     [i] -> format(i <> ".0", pos, round?)
     [i, f] -> [i, f 
                   |> String.pad_trailing(pos, "0")
                   |> String.slice(0..pos - 1)] |> Enum.join(".")
    end
  end
end

IO.inspect NumFmt.format(123.101, 6), label: "123.101000"
#⇒123.101000: "123.101000"

IO.inspect NumFmt.format(123, 3), label: "123.000"
#⇒ 123.000: "123.000"

IO.inspect NumFmt.format(123.101, 1), label: "123.1"
#⇒ 123.1: "123.1"

IO.inspect NumFmt.format(123.000, 0), label: "123"
#⇒ 123: "123"
+1

Source: https://habr.com/ru/post/1016668/


All Articles