aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--src/gleam/float.gleam34
-rw-r--r--test/gleam/float_test.gleam28
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)