根据批量计算数量

时间:2021-04-26 17:23:02

标签: elixir

我有这个代码和测试:

  def order_quantity(:sell, free_quantity, lot_step_size, quantity_precision) do
    {q, _} = :erlang.float_to_binary(Float.floor(free_quantity / lot_step_size) * lot_step_size, decimals: quantity_precision) |> Float.parse()
    q
  end

assert order_quantity(:sell, 0.01977578, 0.00010000, 8) == 0.0197
assert order_quantity(:sell, 0.290709, 0.00100000, 8) == 0.29000000
assert order_quantity(:sell, 111.88800000, 0.01000000, 8) == 111.88

但我对此并不满意——是否有更像 Elixir 的方法来完成相同的计算?

2 个答案:

答案 0 :(得分:1)

如果您关心精度,则应该使用 :decimal 库。 https://hexdocs.pm/decimal/Decimal.html

有了这个,你可以简单地做:

iex> Decimal.round("0.01977578", 4, :down)
#Decimal<0.0197>

其中第一个参数是浮点数或字符串,第二个参数是小数位数,第三个参数是舍入“模式”。

那么您的主要问题是如何从 lot_step_size 浮点数中获取小数位数(整数)。

您可以创建一个函数,该函数可以根据任何给定的手数步长计算 places,但是如果您知道这些只能到小数点后 8 位,那么您可以编写一个更有效(更快)的“模式”每个都这样:

  def places(0.00000001), do: 8
  def places(0.0000001), do: 7
  def places(0.000001), do: 6
  def places(0.00001), do: 5
  def places(0.0001), do: 4
  def places(0.001), do: 3
  def places(0.01), do: 2
  def places(0.1), do: 1

  def order_quantity(:sell, free_quantity, lot_step_size) do
    free_quantity
    |> to_string()
    |> Decimal.round(places(lot_step_size), :down)
    |> Decimal.to_float()
  end

请注意,当我完成后,我会转回浮动,但最好在任何地方使用 Decimal 并避免浮动。

答案 1 :(得分:1)

Float.floor/2 是您的朋友。

answers

此外,您可能最好重新考虑如何通过 iex|1▸ Float.floor 0.01977578, 4 0.0197 iex|2▸ Float.floor 0.290709, 3 0.29 iex|3▸ Float.floor 111.88800000, 2 111.88 。将它作为整数传递可能更有意义,而不是不一定精确浮点数。