web-dev-qa-db-fra.com

Comment formater un nombre à la précision dans Elixir?

Quel est le moyen le plus direct et le plus efficace de le faire dans 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
8
Emily

Je veux juste fournir une alternative à l'excellente réponse de Dogbert.

Il est également possible d'utiliser: 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"
20
MartinElvar

Ces réponses sont pour la plupart étranges. Premièrement, elle n'a rien dit sur la conversion en chaîne. Deuxièmement, il n'est certainement pas nécessaire de sauter dans le pays d'Erlang!

En ordre:

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>

Une fois que vous avez un nombre dans Decimal, vous pouvez faire ce que vous voulez, par exemple. convertir en float, convertir en chaîne, etc.

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

En passant, je vous recommande de ne travailler que dans Decimal jusqu'à ce que vous ayez fini de manipuler les données, par exemple. en utilisant Decimal.mult(num1, num2), Decimal.div(num1, num2), etc. Decimal rock!

5
Madasebrof

Decimal est obsolète et est maintenant supprimé de Elixir. Pour ceux qui trouveront ce post plus tard, voici comment procéder à partir de Elixir v1.6:

123.176
|> Float.round(2)
|> Float.to_string

# => "123.78"
4
Dan Draper

Autant que je sache, il n'y a rien de tel dans la bibliothèque standard d'Elixir, mais vous pouvez utiliser :io_lib.format/2 depuis Erlang pour imprimer un nombre à virgule après le point:

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']

La valeur renvoyée est une iolist, qui peut être convertie en binaire à l'aide de IO.iodata_to_binary/1 si nécessaire (de nombreuses fonctions prenant un binaire peuvent également accepter une iolist, par exemple IO.puts/1):

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

~.0f ne fonctionne pas mais vous pouvez simplement appeler trunc/1 pour cela:

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

J'ai déjà utilisé le paquetage décimal pour cela

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

Dans mon cas, les données étaient déjà au format décimal après avoir été interrogées à partir de la base de données.

1
Mike Buhot

Juste par curiosité, c’est comme ça que je m’impliquerais dans du pur Elixir:

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
Aleksei Matiushkin