Packages
cldr_utils
2.0.5
2.29.7
2.29.6
2.29.5
2.29.4
2.29.3
2.29.2
2.29.1
2.29.0
2.28.3
2.28.2
2.28.1
2.28.0
2.27.0
2.26.0
2.25.0
2.24.2
2.24.1
2.24.0
2.23.1
2.23.0
2.22.0
2.21.0
2.20.0
2.19.2
2.19.1
2.19.0
2.18.0
2.17.2
2.17.1
2.17.0
2.17.0-rc.0
2.16.0
2.15.1
2.15.0
2.14.1
2.14.0
2.13.3
retired
2.13.2
2.13.1
2.13.0
retired
2.12.0
2.11.0
2.10.0
2.9.1
2.9.0
retired
2.8.0
2.7.0
2.6.0
2.5.0
2.4.0
2.3.0
2.2.0
2.1.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
Map, Calendar, Digits, Decimal, HTTP, Macro, Math, and String helpers for ex_cldr.
Current section
59 Versions
Jump to
Current section
59 Versions
Compare versions
6
files changed
+113
additions
-28
deletions
| @@ -1,3 +1,11 @@ | |
| 1 | + ## Changelog for Cldr Utils version 2.0.5 |
| 2 | + |
| 3 | + This is the changelog for Cldr Utils v2.0.4 released on Jnauary 3rd, 2018. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/cldr_utils/tags) |
| 4 | + |
| 5 | + ### Bug Fixes |
| 6 | + |
| 7 | + * Fixes `Cldr.Math.round/3` for floats when rounding is > 0 digits |
| 8 | + |
| 1 9 | ## Changelog for Cldr Utils version 2.0.4 |
| 2 10 | |
| 3 11 | This is the changelog for Cldr Utils v2.0.4 released on Decmber 15th, 2018. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/cldr_utils/tags) |
| @@ -4,7 +4,7 @@ | |
| 4 4 | <<"Map, Calendar, Digits, Macro, Math and String helpers for ex_cldr">>}. |
| 5 5 | {<<"elixir">>,<<"~> 1.5">>}. |
| 6 6 | {<<"files">>, |
| 7 | - [<<"lib">>,<<"lib/cldr">>,<<"lib/cldr/.DS_Store">>,<<"lib/cldr/utils">>, |
| 7 | + [<<"lib">>,<<"lib/cldr">>,<<"lib/cldr/utils">>, |
| 8 8 | <<"lib/cldr/utils/calendar_conversion.ex">>,<<"lib/cldr/utils/digits.ex">>, |
| 9 9 | <<"lib/cldr/utils/helpers.ex">>,<<"lib/cldr/utils/macros.ex">>, |
| 10 10 | <<"lib/cldr/utils/map.ex">>,<<"lib/cldr/utils/math.ex">>, |
| @@ -14,10 +14,10 @@ | |
| 14 14 | {<<"licenses">>,[<<"Apache 2.0">>]}. |
| 15 15 | {<<"links">>, |
| 16 16 | [{<<"Changelog">>, |
| 17 | - <<"https://github.com/kipcole9/cldr_utils/blob/v2.0.4/CHANGELOG.md">>}, |
| 17 | + <<"https://github.com/kipcole9/cldr_utils/blob/v2.0.5/CHANGELOG.md">>}, |
| 18 18 | {<<"GitHub">>,<<"https://github.com/kipcole9/cldr_utils">>}, |
| 19 19 | {<<"Readme">>, |
| 20 | - <<"https://github.com/kipcole9/cldr_utils/blob/v2.0.4/README.md">>}]}. |
| 20 | + <<"https://github.com/kipcole9/cldr_utils/blob/v2.0.5/README.md">>}]}. |
| 21 21 | {<<"name">>,<<"cldr_utils">>}. |
| 22 22 | {<<"requirements">>, |
| 23 23 | [[{<<"app">>,<<"decimal">>}, |
| @@ -25,4 +25,4 @@ | |
| 25 25 | {<<"optional">>,false}, |
| 26 26 | {<<"repository">>,<<"hexpm">>}, |
| 27 27 | {<<"requirement">>,<<"~> 1.5">>}]]}. |
| 28 | - {<<"version">>,<<"2.0.4">>}. |
| 28 | + {<<"version">>,<<"2.0.5">>}. |
| @@ -177,6 +177,7 @@ defmodule Cldr.Math do | |
| 177 177 | This is very likely to lose precision - lots of numbers won't |
| 178 178 | make the round trip conversion. Use with care. Actually, better |
| 179 179 | not to use it at all. |
| 180 | + |
| 180 181 | """ |
| 181 182 | @spec to_float(%Decimal{}) :: float |
| 182 183 | def to_float(%Decimal{sign: sign, coef: coef, exp: exp}) do |
| @@ -775,6 +776,13 @@ defmodule Cldr.Math do | |
| 775 776 | Decimal.round(number, places, mode) |
| 776 777 | end |
| 777 778 | |
| 779 | + def round(number, places, mode) when is_integer(number) do |
| 780 | + number |
| 781 | + |> Decimal.new |
| 782 | + |> Decimal.round(places, mode) |
| 783 | + |> Decimal.to_integer |
| 784 | + end |
| 785 | + |
| 778 786 | # Consistent with Kernel.round/1 |
| 779 787 | def round(number, 0 = places, :half_up = mode) when is_float(number) do |
| 780 788 | number |
| @@ -786,15 +794,98 @@ defmodule Cldr.Math do | |
| 786 794 | |
| 787 795 | def round(number, places, mode) when is_float(number) do |
| 788 796 | number |
| 789 | - |> Decimal.from_float |
| 790 | - |> Decimal.round(places, mode) |
| 791 | - |> to_float |
| 797 | + |> Digits.to_digits() |
| 798 | + |> round_digits(%{decimals: places, rounding: mode}) |
| 799 | + |> Digits.to_number(number) |
| 792 800 | end |
| 793 801 | |
| 794 | - def round(number, places, mode) when is_integer(number) do |
| 795 | - number |
| 796 | - |> Decimal.new |
| 797 | - |> Decimal.round(places, mode) |
| 798 | - |> Decimal.to_integer |
| 802 | + # The next function heads operate on decomposed numbers returned |
| 803 | + # by Digits.to_digits. |
| 804 | + |
| 805 | + # scientific/decimal rounding are the same, we are just varying which |
| 806 | + # digit we start counting from to find our rounding point |
| 807 | + def round_digits(digits_t, options) |
| 808 | + |
| 809 | + # Passing true for decimal places avoids rounding and uses whatever is necessary |
| 810 | + def round_digits(digits_t, %{scientific: true}), do: digits_t |
| 811 | + def round_digits(digits_t, %{decimals: true}), do: digits_t |
| 812 | + |
| 813 | + # rounded away all the decimals... return 0 |
| 814 | + def round_digits(_, %{scientific: dp}) when dp <= 0, do: {[0], 1, true} |
| 815 | + def round_digits({_, place, _}, %{decimals: dp}) when dp + place <= 0, do: {[0], 1, true} |
| 816 | + |
| 817 | + def round_digits(digits_t = {_, place, _}, options = %{decimals: dp}) do |
| 818 | + {digits, place, sign} = do_round(digits_t, dp + place - 1, options) |
| 819 | + {List.flatten(digits), place, sign} |
| 820 | + end |
| 821 | + |
| 822 | + def round_digits(digits_t, options = %{scientific: dp}) do |
| 823 | + {digits, place, sign} = do_round(digits_t, dp, options) |
| 824 | + {List.flatten(digits), place, sign} |
| 825 | + end |
| 826 | + |
| 827 | + defp do_round({digits, place, positive}, round_at, %{rounding: rounding}) do |
| 828 | + case Enum.split(digits, round_at) do |
| 829 | + {l, [least_sig | [tie | rest]]} -> |
| 830 | + case do_incr(l, least_sig, increment?(positive, least_sig, tie, rest, rounding)) do |
| 831 | + [:rollover | digits] -> {digits, place + 1, positive} |
| 832 | + digits -> {digits, place, positive} |
| 833 | + end |
| 834 | + |
| 835 | + {l, [least_sig | []]} -> |
| 836 | + {[l, least_sig], place, positive} |
| 837 | + |
| 838 | + {l, []} -> |
| 839 | + {l, place, positive} |
| 799 840 | end |
| 800 841 | end |
| 842 | + |
| 843 | + # Helper functions for round/2-3 |
| 844 | + defp do_incr(l, least_sig, false), do: [l, least_sig] |
| 845 | + defp do_incr(l, least_sig, true) when least_sig < 9, do: [l, least_sig + 1] |
| 846 | + # else need to cascade the increment |
| 847 | + defp do_incr(l, 9, true) do |
| 848 | + l |
| 849 | + |> Enum.reverse() |
| 850 | + |> cascade_incr |
| 851 | + |> Enum.reverse([0]) |
| 852 | + end |
| 853 | + |
| 854 | + # cascade an increment of decimal digits which could be rolling over 9 -> 0 |
| 855 | + defp cascade_incr([9 | rest]), do: [0 | cascade_incr(rest)] |
| 856 | + defp cascade_incr([d | rest]), do: [d + 1 | rest] |
| 857 | + defp cascade_incr([]), do: [1, :rollover] |
| 858 | + |
| 859 | + @spec increment?(boolean, non_neg_integer | nil, non_neg_integer | nil, list(), atom()) :: |
| 860 | + boolean |
| 861 | + defp increment?(positive, least_sig, tie, rest, round) |
| 862 | + |
| 863 | + # Directed rounding towards 0 (truncate) |
| 864 | + defp increment?(_, _ls, _tie, _, :down), do: false |
| 865 | + # Directed rounding away from 0 (non IEEE option) |
| 866 | + defp increment?(_, _ls, nil, _, :up), do: false |
| 867 | + defp increment?(_, _ls, _tie, _, :up), do: true |
| 868 | + |
| 869 | + # Directed rounding towards +∞ (rounding up / ceiling) |
| 870 | + defp increment?(true, _ls, tie, _, :ceiling) when tie != nil, do: true |
| 871 | + defp increment?(_, _ls, _tie, _, :ceiling), do: false |
| 872 | + |
| 873 | + # Directed rounding towards -∞ (rounding down / floor) |
| 874 | + defp increment?(false, _ls, tie, _, :floor) when tie != nil, do: true |
| 875 | + defp increment?(_, _ls, _tie, _, :floor), do: false |
| 876 | + |
| 877 | + # Round to nearest - tiebreaks by rounding to even |
| 878 | + # Default IEEE rounding, recommended default for decimal |
| 879 | + defp increment?(_, ls, 5, [], :half_even) when Integer.is_even(ls), do: false |
| 880 | + defp increment?(_, _ls, tie, _rest, :half_even) when tie >= 5, do: true |
| 881 | + defp increment?(_, _ls, _tie, _rest, :half_even), do: false |
| 882 | + |
| 883 | + # Round to nearest - tiebreaks by rounding away from zero (same as Elixir Kernel.round) |
| 884 | + defp increment?(_, _ls, tie, _rest, :half_up) when tie >= 5, do: true |
| 885 | + defp increment?(_, _ls, _tie, _rest, :half_up), do: false |
| 886 | + |
| 887 | + # Round to nearest - tiebreaks by rounding towards zero (non IEEE option) |
| 888 | + defp increment?(_, _ls, 5, [], :half_down), do: false |
| 889 | + defp increment?(_, _ls, tie, _rest, :half_down) when tie >= 5, do: true |
| 890 | + defp increment?(_, _ls, _tie, _rest, :half_down), do: false |
| 891 | + end |
| @@ -1,18 +1,4 @@ | |
| 1 1 | defmodule CldrUtils do |
| 2 | - @moduledoc """ |
| 3 | - Documentation for CldrUtils. |
| 4 | - """ |
| 2 | + @moduledoc false |
| 5 3 | |
| 6 | - @doc """ |
| 7 | - Hello world. |
| 8 | - |
| 9 | - ## Examples |
| 10 | - |
| 11 | - iex> CldrUtils.hello() |
| 12 | - :world |
| 13 | - |
| 14 | - """ |
| 15 | - def hello do |
| 16 | - :world |
| 17 | - end |
| 18 4 | end |
Loading more files…