Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/decimal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2463,7 +2463,11 @@ defmodule Decimal do

defp increment?(:down, _, _, _, _), do: false

defp increment?(:up, _, _, _, _), do: true
# Round-up is away from zero, but per the General Decimal Arithmetic spec
# an all-zero discarded part leaves the value unchanged (an exact value is
# never rounded up). Check the discarded digits like :ceiling/:floor do,
# rather than incrementing unconditionally.
defp increment?(:up, _, _, remain, sticky?), do: any_nonzero?(remain, sticky?)

defp increment?(:ceiling, sign, _, remain, sticky?),
do: sign == 1 and any_nonzero?(remain, sticky?)
Expand Down
11 changes: 11 additions & 0 deletions test/decimal/context_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ defmodule Decimal.ContextTest do
assert Decimal.add(~d"0", ~d"-102") == d(-1, 11, 1)
assert Decimal.add(~d"0", ~d"1.1") == d(1, 11, -1)
end)

# :up rounds away from zero only when a discarded digit is nonzero. An
# exact value whose dropped digits are all zero must be left unchanged
# (matches the General Decimal Arithmetic spec and Python's decimal).
Context.with(%Context{precision: 1, rounding: :up}, fn ->
assert Decimal.add(~d"0", ~d"9.0") == d(1, 9, 0)
assert Decimal.add(~d"0", ~d"-9.0") == d(-1, 9, 0)
assert Decimal.mult(~d"9.00", ~d"1") == d(1, 9, 0)
# a nonzero discarded digit still rounds up
assert Decimal.add(~d"0", ~d"3.1") == d(1, 4, 0)
end)
end

test "with_context/2: large exponent gap addition" do
Expand Down