diff options
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | src/gleam/float.gleam | 34 | ||||
-rw-r--r-- | test/gleam/float_test.gleam | 28 |
3 files changed, 59 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 300963e..0e19175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.26.0 - unreleased + +- The `float` module gains the `loosely_equals` function. + ## v0.25.0 - 2022-11-19 - The `bool` module gains the `and` and `or` functions. diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam index b5045ce..b88dac8 100644 --- a/src/gleam/float.gleam +++ b/src/gleam/float.gleam @@ -87,9 +87,11 @@ pub fn compare(a: Float, with b: Float) -> Order { } } -/// Compares two `Float`s within a tolerance. -/// Keep in mind that as this are floats the tolerance won't be exact -/// e.g. 5.3 - 5.0 is not exactly 0.3 in a float +/// Compares two `Float`s within a tolerance and returns an `Order`: +/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. +/// +/// Notice: For `Float`s the tolerance won't be exact: +/// `5.3 - 5.0` is not exactly `0.3`. /// /// ## Examples /// @@ -110,6 +112,32 @@ pub fn loosely_compare( } } +/// Checks for equality of two `Float`s within a tolerance. +/// +/// Notice: For `Float`s the tolerance won't be exact: +/// `5.3 - 5.0` is not exactly `0.3`. +/// +/// ## Examples +/// +/// ```gleam +/// > loosely_equals(5.0, with: 5.3, tolerating: 0.5) +/// True +/// ``` +/// +/// ```gleam +/// > loosely_equals(5.0, with: 5.1, tolerating: 0.1) +/// False +/// ``` +/// +pub fn loosely_equals( + a: Float, + with b: Float, + tolerating tolerance: Float, +) -> Bool { + let difference = absolute_value(a -. b) + difference <=. tolerance +} + /// Compares two `Float`s, returning the smaller of the two. /// /// ## Examples diff --git a/test/gleam/float_test.gleam b/test/gleam/float_test.gleam index 44d9f52..a068647 100644 --- a/test/gleam/float_test.gleam +++ b/test/gleam/float_test.gleam @@ -100,6 +100,26 @@ pub fn loosely_compare_test() { |> should.equal(order.Eq) } +pub fn loosely_equals_test() { + float.loosely_equals(10.2, 10.5, tolerating: 0.) + |> should.be_false + + float.loosely_equals(10.2, with: 10.5, tolerating: 0.31) + |> should.be_true + + float.loosely_equals(10.5, 10.2, 0.31) + |> should.be_true + + float.loosely_equals(10.2, 10.5, 0.29) + |> should.be_false + + float.loosely_equals(10.5, 10.2, 0.29) + |> should.be_false + + float.loosely_equals(-10.2, -10.5, 0.31) + |> should.be_true +} + pub fn ceiling_test() { 8.1 |> float.ceiling @@ -264,7 +284,7 @@ pub fn power_test() { // float.power(-1.0, 0.5) is equivalent to float.square_root(-1.0) // and should return an error as an imaginary number would otherwise - // have to be returned + // have to be returned float.power(-1.0, 0.5) |> should.equal(Error(Nil)) @@ -277,7 +297,7 @@ pub fn power_test() { float.power(0.0, -1.0) |> should.equal(Error(Nil)) - // Check that a negative base and exponent is fine as long as the + // Check that a negative base and exponent is fine as long as the // exponent is not fractional float.power(-2.0, -1.0) |> should.equal(Ok(-0.5)) @@ -369,8 +389,8 @@ pub fn random_test() { with: fn(accumulator, _element) { accumulator +. float.random(min, max) }, ) |> fn(sum) { sum /. int.to_float(iterations) } - |> float.loosely_compare(expected_average, tolerance) - |> should.equal(order.Eq) + |> float.loosely_equals(expected_average, tolerance) + |> should.be_true } test_mean(100, 0.0, 0.0, 5.0) test_mean(1_000, 0.0, 100.0, 5.0) |