Repository navigation
docs: add dedicated documentation for ApproximateEquality - #355
Conversation
Add a comprehensive DocC guide for ApproximateEquality covering: - Background and motivation for approximate equality in floating-point math - Relative and absolute tolerance guidelines and formulas - Special value handling (NaN, infinities, signed zeroes) - Custom norms with AdditiveArithmetic - Mathematical properties (non-transitivity and why not to use for Equatable) Also update RealModule.md to link to the DocC article and restore the Approximate equality section with a link in Sources/RealModule/README.md. Resolves apple#153. Signed-off-by: reginaldalfret <reginaldalfret@gmail.com>
| @@ -0,0 +1,155 @@ | |||
| # Approximate Equality | |||
|
|
|||
| Compare floating-point and numerical values up to a tolerance. | |||
There was a problem hiding this comment.
The abstract for this article is tricky, because these operations are very general. Formally they don't only work for floating-point or even "numerical" values, though that's the most obvious use case. Mathematically it's roughly something like "compare elements of a normed linear space with tolerance", but that's obviously not a great fit for this context, since we'd have to spend a few dozen paragraphs defining each of those words. I'll think about this a bit, but if you have other suggestions in the meantime, I'd love to hear them.
| Floating-point arithmetic is not exact, so two values that are mathematically | ||
| equal may differ slightly once they have been computed. Comparing such values | ||
| with `==` is usually a mistake: the test will fail for inputs that are equal | ||
| in every way that matters to your program. |
There was a problem hiding this comment.
This paragraph is well-intentioned, but misleading. It is frequently completely appropriate to compare floating-point values with exact equality, and frequently desirable to compare non-floating-point values with an approximate equality. Rounding error is one reason why approximate equality can be desirable, but it is not the only one (and not even the primary reason--most nontrivial numerical algorithms have inherent error separate from floating-point considerations, and most measurements are inexact to begin with).
I would just remove this, I think.
| let x = 0.1 + 0.2 | ||
| x == 0.3 // false | ||
| x.isApproximatelyEqual(to: 0.3) // true | ||
| ``` |
There was a problem hiding this comment.
This is great. If you're open to it, a worked example with a non-Numeric type would also be fantastic here.
| result.isApproximatelyEqual( | ||
| to: expected, | ||
| absoluteTolerance: error, | ||
| relativeTolerance: error |
There was a problem hiding this comment.
Having relativeTolerance == absoluteTolerance only really makes sense in cases where values are expected to lie on an integral grid due to algorithmic considerations. It can certainly happen, but isn't the norm. We should either explain that or talk a little about how to chose values for these appropriately.
|
|
||
| For a complex value, the default norm `\.magnitude` measures the difference | ||
| inside a square region. To test instead whether a value lies inside a circle of | ||
| radius `0.001` centered at `1 + 0i`, pass the Euclidean length as the norm: |
There was a problem hiding this comment.
Should mention here that the advantage of using \.magnitude for complex values is that it is finite and non-zero for any finite non-zero value. It never overflows or underflows, so can be used even with very poorly scaled values. That's not true for \.length or the one-norm, or any other common choice.
|
|
||
| Because floating-point arithmetic is inexact, two values that are | ||
| mathematically equal often differ slightly once computed, so comparing them | ||
| with `==` is usually a mistake. |
…raction and tolerances Signed-off-by: reginaldalfret <reginaldalfret@gmail.com>
| scenarios, exact equality (`==`) may be too strict or inappropriate, and an | ||
| approximate equality comparison is needed instead. Conversely, exact equality | ||
| remains entirely appropriate when checking for identical values, sentinel states, | ||
| or integers. |
There was a problem hiding this comment.
This is a really nice improvement, thanks!
docs: add dedicated documentation for ApproximateEquality
Summary
This PR addresses #153 by adding a dedicated DocC documentation article for
ApproximateEquality, providing comprehensive background, examples, and technical guidance for comparing numerical values up to a tolerance.Specifically:
Sources/RealModule/Documentation.docc/ApproximateEquality.md:==is usually inappropriate for floating-point values and introducesisApproximatelyEqual..ulpOfOne.squareRoot(), scale calculation) and absolute tolerance (especially near zero), along with code snippets.NaN, infinities,+0.0vs-0.0).AdditiveArithmetic(e.g. Euclidean length\.lengthonComplexModule).Equatable.Sources/RealModule/Documentation.docc/RealModule.md:<doc:ApproximateEquality>.Sources/RealModule/README.md:## Approximate equalityoverview section with an example and a link to the new documentation article as requested in Refactor README.md and include Approximate Equality as part of the RealModule. #150 / Add dedicated markdown docs for ApproximateEquality #153.Resolves #153.
Testing
Documentation-only changes; verified markdown formatting, links, and doc references.