我有这个代码和测试:
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 的方法来完成相同的计算?
答案 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
。将它作为整数传递可能更有意义,而不是不一定精确浮点数。