Skip to content

Instantly share code, notes, and snippets.

@jodonnell
Created December 13, 2015 20:52
Show Gist options
  • Save jodonnell/bb28c736b3cd9a3bbd6d to your computer and use it in GitHub Desktop.
Save jodonnell/bb28c736b3cd9a3bbd6d to your computer and use it in GitHub Desktop.
[#HashDict<[{"number", 3400}, {"comments", 14},
{"title", "Float.round is inconsistent"},
{"created_at", "2015-06-17T13:04:45Z"}, {"state", "open"}, {"locked", false},
{"url", "https://api.github.com/repos/elixir-lang/elixir/issues/3400"},
{"comments_url",
"https://api.github.com/repos/elixir-lang/elixir/issues/3400/comments"},
{"labels",
[[{"url",
"https://api.github.com/repos/elixir-lang/elixir/labels/App:Elixir"},
{"name", "App:Elixir"}, {"color", "CCCCCC"}],
[{"url", "https://api.github.com/repos/elixir-lang/elixir/labels/Kind:Bug"},
{"name", "Kind:Bug"}, {"color", "e10c02"}],
[{"url",
"https://api.github.com/repos/elixir-lang/elixir/labels/Level:Advanced"},
{"name", "Level:Advanced"}, {"color", "f7c6c7"}]]}, {"id", 89011434},
{"labels_url",
"https://api.github.com/repos/elixir-lang/elixir/issues/3400/labels{/name}"},
{"events_url",
"https://api.github.com/repos/elixir-lang/elixir/issues/3400/events"},
{"html_url", "https://github.com/elixir-lang/elixir/issues/3400"},
{"user",
[{"login", "ewildgoose"}, {"id", 13366},
{"avatar_url", "https://avatars.githubusercontent.com/u/13366?v=3"},
{"gravatar_id", ""}, {"url", "https://api.github.com/users/ewildgoose"},
{"html_url", "https://github.com/ewildgoose"},
{"followers_url", "https://api.github.com/users/ewildgoose/followers"},
{"following_url",
"https://api.github.com/users/ewildgoose/following{/other_user}"},
{"gists_url", "https://api.github.com/users/ewildgoose/gists{/gist_id}"},
{"starred_url",
"https://api.github.com/users/ewildgoose/starred{/owner}{/repo}"},
{"subscriptions_url",
"https://api.github.com/users/ewildgoose/subscriptions"},
{"organizations_url", "https://api.github.com/users/ewildgoose/orgs"},
{"repos_url", "https://api.github.com/users/ewildgoose/repos"},
{"events_url", "https://api.github.com/users/ewildgoose/events{/privacy}"},
{"received_events_url",
"https://api.github.com/users/ewildgoose/received_events"},
{"type", "User"}, {"site_admin", false}]},
{"body",
"The rounding from Float.round is inconsistent, eg\r\n\r\niex(121)> Kernel.round(1.255 * 100) / 100\r\n1.25\r\n\r\niex(123)> Kernel.round(125.5) / 100\r\n1.26\r\n\r\niex> Kernel.round(Kernel.round(1.255 * 1000) / 10) / 100\r\n1.26\r\n\r\n\r\nThe core issue is numerical instability due to the multiplication by a power of 10 (which itself has to be encoded as an approximation in floating point format)\r\n\r\nThe following *appears* to correctly implement the same rounding function as Kernel.round (ie round away from zero) without instability. However, it would be sensible to include a test harness for very large/small numbers and also floats in \"denomalised\" form.\r\n\r\n```\r\n @spec round(float, 0..15) :: float\r\n def round(number, precision \\\\ 0) when is_float(number) and precision in 0..15 do\r\n power = power_of_10(precision)\r\n power2 = power_of_10(precision+1)\r\n # Avoid numerical instability by pre-rounding to one extra digit of precision\r\n Kernel.round(Kernel.round(number * power2) / 10) / power\r\n end\r\n\r\n Enum.reduce 0..21, 1, fn x, acc ->\r\n defp power_of_10(unquote(x)), do: unquote(acc)\r\n acc * 10\r\n end\r\n```"},
{"assignee", :null}, {"closed_at", :null}, {"milestone", :null},
{"updated_at", "2015-06-22T11:55:15Z"}]>]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment