elmcraft / core-extra / Float.Extra

Convenience functions for dealing with Floats.

Equality

aboutEqual : Basics.Float -> Basics.Float -> Basics.Bool

Comparing Floats with == is usually wrong, unless you basically care for reference equality, since floating point numbers often have small precision drift.

0.1 + 0.2 == 0.3 --> False

This function implements an approximation where we are asking - are these values close enough that we can consider their difference to be due to floating point drift rather than a result of meaningful difference in calculation?

(0.1 + 0.2) |> Float.Extra.aboutEqual 0.3 --> True

Note: this is unlikely to be appropriate if you are performing computations much smaller than one.

(0.00001 + 0.00002) |> Float.Extra.aboutEqual 0.00003 --> True

This value handles Infinity and NaN like so:

(1 / 0) |> Float.Extra.aboutEqual (100 / 0) --> True

(0 / 0) |> Float.Extra.aboutEqual (0 / 0) --> False

Formatting Floats

toFixedDecimalPlaces : Basics.Int -> Basics.Float -> String

Fix a float value represented to a certain number of decimal places as a string.

Float.Extra.toFixedDecimalPlaces 3 0.0326232 --> "0.033"

toFixedSignificantDigits : Basics.Int -> Basics.Float -> String

Fix a float value represented as a string to a certain number of significant digits.

Float.Extra.toFixedSignificantDigits 2 1.435 --> "1.4"

Float.Extra.toFixedSignificantDigits 2 545435 --> "550000"

Float.Extra.toFixedSignificantDigits 2 0.0039 --> "0.0039"

boundaryValuesAsUnicode : (Basics.Float -> String) -> Basics.Float -> String

When showing Float values to users, we generally don't particularly want them to see programmer-y values like NaN or Infinity. This function wraps a number formatting routine, but replaces those values with unicode symbols:

format : Float -> String
format =
    Float.Extra.toFixedSignificantDigits 3
        |> Float.Extra.boundaryValuesAsUnicode

format (0 / 0) --> "∅"
format (1 / 0) --> "∞"
format (-1 / 0) --> "-∞"
format (1 / 3) -> "0.333"

Of course using this is unsuitable for when you want the numbers to be machine readable.

Ranges

range : Basics.Float -> Basics.Float -> Basics.Float -> List Basics.Float

Returns a List containing an arithmetic progression, similar to the Python built-in range.

Takes a start, stop and step argument. The stop value is exclusive; it is not included in the result. If step is positive, the last element is the largest start + i * step less than stop; if step is negative, the last element is the smallest start + i * step greater than stop. If the returned list would contain an infinite number of values, an empty range is returned.

The arguments are not required to be whole numbers; however, the results are more predictable if they are.

Differences from List.range from the standard library:

Modular arithmetic

modBy : Basics.Float -> Basics.Float -> Basics.Float

Perform modular arithmetic involving floating point numbers.

The sign of the result is the same as the sign of the modulus in Float.Extra.modBy modulus x.

Float.Extra.modBy 2.5 5 --> 0

Float.Extra.modBy 2 4.5 == 0.5

Float.Extra.modBy 2 -4.5 == 1.5

Float.Extra.modBy -2 4.5 == -1.5