From 70d7a28a36098285646a461ff4170d412c7ac1b5 Mon Sep 17 00:00:00 2001 From: Justin Jaffray Date: Wed, 25 Dec 2013 10:35:24 -0500 Subject: [PATCH 1/2] Fix Float.parse to handle numbers of the form "-0.x" Since Float.parse uses Integer.parse, the -0 would be parsed independently of what came after the decimal point and would become 0 --- lib/elixir/lib/float.ex | 9 +++++++++ lib/elixir/test/elixir/float_test.exs | 1 + 2 files changed, 10 insertions(+) diff --git a/lib/elixir/lib/float.ex b/lib/elixir/lib/float.ex index ca273a68a4a..fc8d9145673 100644 --- a/lib/elixir/lib/float.ex +++ b/lib/elixir/lib/float.ex @@ -22,6 +22,15 @@ defmodule Float do """ @spec parse(binary) :: { float, binary } | :error + + # Integer.parse will parse "-0" as 0, so it needs to be handled separately + def parse(<< "-0.", rest :: binary >>) do + case parse(<< ?., rest :: binary >>, 0) do + :error -> :error + { parsed, remainder } -> { -parsed, remainder } + end + end + def parse(binary) when is_binary(binary) do case Integer.parse binary do :error -> :error diff --git a/lib/elixir/test/elixir/float_test.exs b/lib/elixir/test/elixir/float_test.exs index c42393b0cba..3396beb7f0d 100644 --- a/lib/elixir/test/elixir/float_test.exs +++ b/lib/elixir/test/elixir/float_test.exs @@ -6,6 +6,7 @@ defmodule FloatTest do test :parse do assert Float.parse("12") === {12.0, ""} assert Float.parse("-12") === {-12.0, ""} + assert Float.parse("-0.1") === {-0.1, ""} assert Float.parse("123456789") === {123456789.0, ""} assert Float.parse("12.5") === {12.5, ""} assert Float.parse("12.524235") === {12.524235, ""} From 8c6e31bda09a07bbc90fa9c58644865d4af8d129 Mon Sep 17 00:00:00 2001 From: Justin Jaffray Date: Wed, 25 Dec 2013 13:25:36 -0500 Subject: [PATCH 2/2] Pattern match just on "-" --- lib/elixir/lib/float.ex | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/elixir/lib/float.ex b/lib/elixir/lib/float.ex index fc8d9145673..7349c7f4e49 100644 --- a/lib/elixir/lib/float.ex +++ b/lib/elixir/lib/float.ex @@ -22,37 +22,40 @@ defmodule Float do """ @spec parse(binary) :: { float, binary } | :error - - # Integer.parse will parse "-0" as 0, so it needs to be handled separately - def parse(<< "-0.", rest :: binary >>) do - case parse(<< ?., rest :: binary >>, 0) do + def parse("-" <> binary) do + case parse_unsign(binary) do :error -> :error - { parsed, remainder } -> { -parsed, remainder } + { number, remainder } -> { -number, remainder } end end - def parse(binary) when is_binary(binary) do + def parse(binary) do + parse_unsign(binary) + end + + defp parse_unsign("-" <> binary), do: :error + defp parse_unsign(binary) when is_binary(binary) do case Integer.parse binary do :error -> :error - { integer_part, after_integer } -> parse after_integer, integer_part + { integer_part, after_integer } -> parse_unsign after_integer, integer_part end end # Dot followed by digit is required afterwards or we are done - defp parse(<< ?., char, rest :: binary >>, int) when char in ?0..?9 do - parse(rest, char - ?0, 1, int) + defp parse_unsign(<< ?., char, rest :: binary >>, int) when char in ?0..?9 do + parse_unsign(rest, char - ?0, 1, int) end - defp parse(rest, int) do + defp parse_unsign(rest, int) do { :erlang.float(int), rest } end # Handle decimal points - defp parse(<< char, rest :: binary >>, float, decimal, int) when char in ?0..?9 do - parse rest, 10 * float + (char - ?0), decimal + 1, int + defp parse_unsign(<< char, rest :: binary >>, float, decimal, int) when char in ?0..?9 do + parse_unsign rest, 10 * float + (char - ?0), decimal + 1, int end - defp parse(<< ?e, after_e :: binary >>, float, decimal, int) do + defp parse_unsign(<< ?e, after_e :: binary >>, float, decimal, int) do case Integer.parse after_e do :error -> # Note we rebuild the binary here instead of breaking it apart at @@ -65,7 +68,7 @@ defmodule Float do end end - defp parse(bitstring, float, decimal, int) do + defp parse_unsign(bitstring, float, decimal, int) do { floatify(int, float, decimal), bitstring } end