Elixir - 将字符串解析为浮动导致错误

时间:2017-08-10 08:58:13

标签: elixir elixir-framework

我试图将字符串解析为浮点数时遇到此错误:

case insert_product_shop(conn, existing_product.id, existing_shop.id, String.to_float(posted_product["price"])) do

错误:

20:45:29.766 [error] #PID<0.342.0> running Api.Router terminated
Server: 172.20.10.2:4000 (http)
Request: POST /products
** (exit) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.binary_to_float(58.25)
        (api) lib/api/router.ex:120: anonymous fn/1 in Api.Router.do_match/4
        (api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
        (api) lib/plug/debugger.ex:123: Api.Router.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.exe
cute/4

当我改为

case insert_product_shop(conn, existing_product.id, existing_shop.id, Float.parse(posted_product["price"])) do
:

我明白了:

20:54:12.769 [error] #PID<0.336.0> running Api.Router terminated
Server: 172.20.10.2:4000 (http)
Request: POST /products
** (exit) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.binary_to_float(24)
        (api) lib/api/router.ex:82: anonymous fn/1 in Api.Router.do_match/4
        (api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
        (api) lib/plug/debugger.ex:123: Api.Router.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.exe
cute/4

如何从字符串正确解析为float?我是否也可以允许它为字符串或浮点数,如果是字符串,则解析为浮点数?

1 个答案:

答案 0 :(得分:4)

根据错误,看起来输入已经是Float

** (ArgumentError) argument error
    :erlang.binary_to_float(58.25)

事实上,如果输入不是String.to_float/1,则String会引发错误。

iex(1)> String.to_float(58.25)
** (ArgumentError) argument error
    :erlang.binary_to_float(58.25)
iex(1)> String.to_float("58.25")
58.25

另请注意,如果输入没有小数位,String.to_float/1也会抱怨。

iex(2)> String.to_float("58")
** (ArgumentError) argument error
    :erlang.binary_to_float("58")
iex(2)> String.to_float("58.0")
58.0

您需要编写自定义函数。我不确定posted_product["price"]的来源,以及您是否希望它有不同的输入类型。这可能是一个错误。

一种可能的解决方法是始终将输入转换为String,并使用Float.parse/1

iex(12)> {f, _} = Float.parse(to_string("58.0"))
{58.0, ""}
iex(13)> f
58.0
iex(14)> {f, _} = Float.parse(to_string(58.0))
{58.0, ""}
iex(15)> f
58.0

请注意,Float.parse/1可能会返回:error,因此您必须处理该问题。

另一个可能稍微提高效率的选项是仅在必要时使用is_float/1is_string/1来处理转化。

defmodule Price do
  def to_float(input) when is_float(input) do
    input
  end
  def to_float(input) do
    case Float.parse(to_string(input)) do
      {f, ""} -> f
      _       -> :error
    end
  end
end

iex(2)> Price.to_float(32)
32.0
iex(3)> Price.to_float(32.0)
32.0
iex(4)> Price.to_float("32")
32.0