From 256aa9212fcc8a9b173d651802fb78c9982d7b3d Mon Sep 17 00:00:00 2001 From: mazuh Date: Mon, 1 Apr 2024 22:46:46 -0300 Subject: [PATCH] add `gte?/2` and `lte?/2` (and fix small typos on `gt`/`lt` docs) --- lib/decimal.ex | 72 +++++++++++++++++++++++++++++++++++++++++-- test/decimal_test.exs | 18 +++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/lib/decimal.ex b/lib/decimal.ex index 5f61a3c..dfbb67d 100644 --- a/lib/decimal.ex +++ b/lib/decimal.ex @@ -447,7 +447,7 @@ defmodule Decimal do def eq?(num1, num2), do: compare(num1, num2) == :eq @doc """ - Compares two numbers numerically and returns `true` if the the first argument + Compares two numbers numerically and returns `true` if the first argument is greater than the second, otherwise `false`. If one the operands is a quiet NaN this operation will always return `false`. @@ -467,7 +467,7 @@ defmodule Decimal do def gt?(num1, num2), do: compare(num1, num2) == :gt @doc """ - Compares two numbers numerically and returns `true` if the the first number is + Compares two numbers numerically and returns `true` if the first number is less than the second number, otherwise `false`. If one of the operands is a quiet NaN this operation will always return `false`. @@ -486,6 +486,74 @@ defmodule Decimal do def lt?(_num1, %Decimal{coef: :NaN}), do: false def lt?(num1, num2), do: compare(num1, num2) == :lt + @doc """ + Compares two numbers numerically and returns `true` if + the first argument is greater than or equal the second, + otherwise `false`. + + If one the operands is a quiet NaN this operation + will always return `false`. + + ## Examples + + iex> Decimal.gte?("1.3", "1.3") + true + + iex> Decimal.gte?("1.3", "1.2") + true + + iex> Decimal.gte?("1.2", "1.3") + false + + """ + doc_since("2.2.0") + @spec gte?(decimal, decimal) :: boolean + + def gte?(%Decimal{coef: :NaN}, _num2), do: false + def gte?(_num1, %Decimal{coef: :NaN}), do: false + + def gte?(num1, num2) do + case compare(num1, num2) do + :gt -> true + :eq -> true + _ -> false + end + end + + @doc """ + Compares two numbers numerically and returns `true` if + the first number is less than or equal the second number, + otherwise `false`. + + If one of the operands is a quiet NaN this operation + will always return `false`. + + ## Examples + + iex> Decimal.lte?("1.1", "1.1") + true + + iex> Decimal.lte?("1.1", "1.2") + true + + iex> Decimal.lte?("1.4", "1.2") + false + + """ + doc_since("2.2.0") + @spec lte?(decimal, decimal) :: boolean + + def lte?(%Decimal{coef: :NaN}, _num2), do: false + def lte?(_num1, %Decimal{coef: :NaN}), do: false + + def lte?(num1, num2) do + case compare(num1, num2) do + :lt -> true + :eq -> true + _ -> false + end + end + @doc """ Divides two numbers. diff --git a/test/decimal_test.exs b/test/decimal_test.exs index d79a15e..1651bc6 100644 --- a/test/decimal_test.exs +++ b/test/decimal_test.exs @@ -295,6 +295,24 @@ defmodule DecimalTest do refute Decimal.lt?(~d"1", ~d"nan") end + test "gte?/2" do + assert Decimal.gte?(~d"420", ~d"42e1") + assert Decimal.gte?(~d"1", ~d"0") + refute Decimal.gte?(~d"0", ~d"1") + assert Decimal.gte?(~d"0", ~d"-0") + refute Decimal.gte?(~d"nan", ~d"1") + refute Decimal.gte?(~d"1", ~d"nan") + end + + test "lte?/2" do + assert Decimal.lte?(~d"420", ~d"42e1") + refute Decimal.lte?(~d"1", ~d"0") + assert Decimal.lte?(~d"0", ~d"1") + assert Decimal.lte?(~d"0", ~d"-0") + refute Decimal.lte?(~d"nan", ~d"1") + refute Decimal.lte?(~d"1", ~d"nan") + end + test "div/2" do Context.with(%Context{precision: 5, rounding: :half_up}, fn -> assert Decimal.div(~d"1", ~d"3") == d(1, 33333, -5)