Skip to main content

# Float

Double precision (64-bit) floating-point numbers in IEEE 754 representation.

This module contains common floating-point constants and utility functions.

Notation for special values in the documentation below: `+inf`: Positive infinity `-inf`: Negative infinity `NaN`: "not a number" (can have different sign bit values, but `NaN != NaN` regardless of the sign).

Note: Floating point numbers have limited precision and operations may inherently result in numerical errors.

Examples of numerical errors:

``0.1 + 0.1 + 0.1 == 0.3 // => false``
``1e16 + 1.0 != 1e16 // => false``

(and many more cases)

Advice:

• Floating point number comparisons by `==` or `!=` are discouraged. Instead, it is better to compare floating-point numbers with a numerical tolerance, called epsilon.

Example:

``import Float "mo:base/Float";let x = 0.1 + 0.1 + 0.1;let y = 0.3;let epsilon = 1e-6; // This depends on the application case (needs a numerical error analysis).Float.equalWithin(x, y, epsilon) // => true``
• For absolute precision, it is recommened to encode the fraction number as a pair of a Nat for the base and a Nat for the exponent (decimal point).

NaN sign:

• The NaN sign is only applied by `abs`, `neg`, and `copySign`. Other operations can have an arbitrary sign bit for NaN results.

## Type `Float`​

``type Float = Prim.Types.Float``

64-bit floating point number type.

## Value `pi`​

``let pi : Float``

Ratio of the circumference of a circle to its diameter. Note: Limited precision.

## Value `e`​

``let e : Float``

Base of the natural logarithm. Note: Limited precision.

## Function `isNaN`​

``func isNaN(number : Float) : Bool``

Determines whether the `number` is a `NaN` ("not a number" in the floating point representation). Notes:

• Equality test of `NaN` with itself or another number is always `false`.
• There exist many internal `NaN` value representations, such as positive and negative NaN, signalling and quiet NaNs, each with many different bit representations.

Example:

``import Float "mo:base/Float";Float.isNaN(0.0/0.0) // => true``

## Value `abs`​

``let abs : (x : Float) -> Float``

Returns the absolute value of `x`.

Special cases:

``abs(+inf) => +infabs(-inf) => +infabs(-NaN)  => +NaNabs(-0.0) => 0.0``

Example:

``import Float "mo:base/Float";Float.abs(-1.2) // => 1.2``

## Value `sqrt`​

``let sqrt : (x : Float) -> Float``

Returns the square root of `x`.

Special cases:

``sqrt(+inf) => +infsqrt(-0.0) => -0.0sqrt(x)    => NaN if x < 0.0sqrt(NaN)  => NaN``

Example:

``import Float "mo:base/Float";Float.sqrt(6.25) // => 2.5``

## Value `ceil`​

``let ceil : (x : Float) -> Float``

Returns the smallest integral float greater than or equal to `x`.

Special cases:

``ceil(+inf) => +infceil(-inf) => -infceil(NaN)  => NaNceil(0.0)  => 0.0ceil(-0.0) => -0.0``

Example:

``import Float "mo:base/Float";Float.ceil(1.2) // => 2.0``

## Value `floor`​

``let floor : (x : Float) -> Float``

Returns the largest integral float less than or equal to `x`.

Special cases:

``floor(+inf) => +inffloor(-inf) => -inffloor(NaN)  => NaNfloor(0.0)  => 0.0floor(-0.0) => -0.0``

Example:

``import Float "mo:base/Float";Float.floor(1.2) // => 1.0``

## Value `trunc`​

``let trunc : (x : Float) -> Float``

Returns the nearest integral float not greater in magnitude than `x`. This is equivalent to returning `x` with truncating its decimal places.

Special cases:

``trunc(+inf) => +inftrunc(-inf) => -inftrunc(NaN)  => NaNtrunc(0.0)  => 0.0trunc(-0.0) => -0.0``

Example:

``import Float "mo:base/Float";Float.trunc(2.75) // => 2.0``

## Value `nearest`​

``let nearest : (x : Float) -> Float``

Returns the nearest integral float to `x`. A decimal place of exactly .5 is rounded up for `x > 0` and rounded down for `x < 0`

Special cases:

``nearest(+inf) => +infnearest(-inf) => -infnearest(NaN)  => NaNnearest(0.0)  => 0.0nearest(-0.0) => -0.0``

Example:

``import Float "mo:base/Float";Float.nearest(2.75) // => 3.0``

## Value `copySign`​

``let copySign : (x : Float, y : Float) -> Float``

Returns `x` if `x` and `y` have same sign, otherwise `x` with negated sign.

The sign bit of zero, infinity, and `NaN` is considered.

Example:

``import Float "mo:base/Float";Float.copySign(1.2, -2.3) // => -1.2``

## Value `min`​

``let min : (x : Float, y : Float) -> Float``

Returns the smaller value of `x` and `y`.

Special cases:

``min(NaN, y) => NaN for any Float ymin(x, NaN) => NaN for any Float x``

Example:

``import Float "mo:base/Float";Float.min(1.2, -2.3) // => -2.3 (with numerical imprecision)``

## Value `max`​

``let max : (x : Float, y : Float) -> Float``

Returns the larger value of `x` and `y`.

Special cases:

``max(NaN, y) => NaN for any Float ymax(x, NaN) => NaN for any Float x``

Example:

``import Float "mo:base/Float";Float.max(1.2, -2.3) // => 1.2``

## Value `sin`​

``let sin : (x : Float) -> Float``

Returns the sine of the radian angle `x`.

Special cases:

``sin(+inf) => NaNsin(-inf) => NaNsin(NaN) => NaN``

Example:

``import Float "mo:base/Float";Float.sin(Float.pi / 2) // => 1.0``

## Value `cos`​

``let cos : (x : Float) -> Float``

Returns the cosine of the radian angle `x`.

Special cases:

``cos(+inf) => NaNcos(-inf) => NaNcos(NaN)  => NaN``

Example:

``import Float "mo:base/Float";Float.cos(Float.pi / 2) // => 0.0 (with numerical imprecision)``

## Value `tan`​

``let tan : (x : Float) -> Float``

Returns the tangent of the radian angle `x`.

Special cases:

``tan(+inf) => NaNtan(-inf) => NaNtan(NaN)  => NaN``

Example:

``import Float "mo:base/Float";Float.tan(Float.pi / 4) // => 1.0 (with numerical imprecision)``

## Value `arcsin`​

``let arcsin : (x : Float) -> Float``

Returns the arc sine of `x` in radians.

Special cases:

``arcsin(x)   => NaN if x > 1.0arcsin(x)   => NaN if x < -1.0arcsin(NaN) => NaN``

Example:

``import Float "mo:base/Float";Float.arcsin(1.0) // => Float.pi / 2``

## Value `arccos`​

``let arccos : (x : Float) -> Float``

Returns the arc cosine of `x` in radians.

Special cases:

``arccos(x)  => NaN if x > 1.0arccos(x)  => NaN if x < -1.0arcos(NaN) => NaN``

Example:

``import Float "mo:base/Float";Float.arccos(1.0) // => 0.0``

## Value `arctan`​

``let arctan : (x : Float) -> Float``

Returns the arc tangent of `x` in radians.

Special cases:

``arctan(+inf) => pi / 2arctan(-inf) => -pi / 2arctan(NaN)  => NaN``

Example:

``import Float "mo:base/Float";Float.arctan(1.0) // => Float.pi / 4``

## Value `arctan2`​

``let arctan2 : (y : Float, x : Float) -> Float``

Given `(y,x)`, returns the arc tangent in radians of `y/x` based on the signs of both values to determine the correct quadrant.

Special cases:

``arctan2(0.0, 0.0)   => 0.0arctan2(-0.0, 0.0)  => -0.0arctan2(0.0, -0.0)  => piarctan2(-0.0, -0.0) => -piarctan2(+inf, +inf) => pi / 4arctan2(+inf, -inf) => 3 * pi / 4arctan2(-inf, +inf) => -pi / 4arctan2(-inf, -inf) => -3 * pi / 4arctan2(NaN, x)     => NaN for any Float xarctan2(y, NaN)     => NaN for any Float y``

Example:

``import Float "mo:base/Float";let sqrt2over2 = Float.sqrt(2) / 2;Float.arctan2(sqrt2over2, sqrt2over2) // => Float.pi / 4``

## Value `exp`​

``let exp : (x : Float) -> Float``

Returns the value of `e` raised to the `x`-th power.

Special cases:

``exp(+inf) => +infexp(-inf) => 0.0exp(NaN)  => NaN``

Example:

``import Float "mo:base/Float";Float.exp(1.0) // => Float.e``

## Value `log`​

``let log : (x : Float) -> Float``

Returns the natural logarithm (base-`e`) of `x`.

Special cases:

``log(0.0)  => -inflog(-0.0) => -inflog(x)    => NaN if x < 0.0log(+inf) => +inflog(NaN)  => NaN``

Example:

``import Float "mo:base/Float";Float.log(Float.e) // => 1.0``

## Function `format`​

``func format(fmt : {#fix : Nat8; #exp : Nat8; #gen : Nat8; #hex : Nat8; #exact}, x : Float) : Text``

Formatting. `format(fmt, x)` formats `x` to `Text` according to the formatting directive `fmt`, which can take one of the following forms:

• `#fix prec` as fixed-point format with `prec` digits
• `#exp prec` as exponential format with `prec` digits
• `#gen prec` as generic format with `prec` digits
• `#hex prec` as hexadecimal format with `prec` digits
• `#exact` as exact format that can be decoded without loss.

`-0.0` is formatted with negative sign bit. Positive infinity is formatted as `inf`. Negative infinity is formatted as `-inf`. `NaN` is formatted as `NaN` or `-NaN` depending on its sign bit.

Example:

``import Float "mo:base/Float";Float.format(#exp 3, 123.0) // => "1.230e+02"``

## Value `toText`​

``let toText : Float -> Text``

Conversion to Text. Use `format(fmt, x)` for more detailed control.

`-0.0` is formatted with negative sign bit. Positive infinity is formatted as `inf`. Negative infinity is formatted as `-inf`. `NaN` is formatted as `NaN` or `-NaN` depending on its sign bit.

Example:

``import Float "mo:base/Float";Float.toText(0.12) // => "0.12"``

## Value `toInt64`​

``let toInt64 : Float -> Int64``

Conversion to Int64 by truncating Float, equivalent to `toInt64(trunc(f))`

Traps if the floating point number is larger or smaller than the representable Int64. Also traps for `inf`, `-inf`, and `NaN`.

Example:

``import Float "mo:base/Float";Float.toInt64(-12.3) // => -12``

## Value `fromInt64`​

``let fromInt64 : Int64 -> Float``

Conversion from Int64.

Note: The floating point number may be imprecise for large or small Int64.

Example:

``import Float "mo:base/Float";Float.fromInt64(-42) // => -42.0``

## Value `toInt`​

``let toInt : Float -> Int``

Conversion to Int.

Traps for `inf`, `-inf`, and `NaN`.

Example:

``import Float "mo:base/Float";Float.toInt(1.2e6) // => +1_200_000``

## Value `fromInt`​

``let fromInt : Int -> Float``

Conversion from Int. May result in `Inf`.

Note: The floating point number may be imprecise for large or small Int values. Returns `inf` if the integer is greater than the maximum floating point number. Returns `-inf` if the integer is less than the minimum floating point number.

Example:

``import Float "mo:base/Float";Float.fromInt(-123) // => -123.0``

## Function `equal`​

``func equal(x : Float, y : Float) : Bool``

Returns `x == y`. @deprecated Use `Float.equalWithin()` as this function does not consider numerical errors.

## Function `notEqual`​

``func notEqual(x : Float, y : Float) : Bool``

Returns `x != y`. @deprecated Use `Float.notEqualWithin()` as this function does not consider numerical errors.

## Function `equalWithin`​

``func equalWithin(x : Float, y : Float, epsilon : Float) : Bool``

Determines whether `x` is equal to `y` within the defined tolerance of `epsilon`. The `epsilon` considers numerical erros, see comment above. Equivalent to `Float.abs(x - y) <= epsilon` for a non-negative epsilon.

Traps if `epsilon` is negative or `NaN`.

Special cases:

``equalWithin(+0.0, -0.0, epsilon) => true for any `epsilon >= 0.0`equalWithin(-0.0, +0.0, epsilon) => true for any `epsilon >= 0.0`equalWithin(+inf, +inf, epsilon) => true for any `epsilon >= 0.0`equalWithin(-inf, -inf, epsilon) => true for any `epsilon >= 0.0`equalWithin(x, NaN, epsilon)     => false for any x and `epsilon >= 0.0`equalWithin(NaN, y, epsilon)     => false for any y and `epsilon >= 0.0```

Example:

``import Float "mo:base/Float";let epsilon = 1e-6;Float.equalWithin(-12.3, -1.23e1, epsilon) // => true``

## Function `notEqualWithin`​

``func notEqualWithin(x : Float, y : Float, epsilon : Float) : Bool``

Determines whether `x` is not equal to `y` within the defined tolerance of `epsilon`. The `epsilon` considers numerical erros, see comment above. Equivalent to `not equal(x, y, epsilon)`.

Traps if `epsilon` is negative or `NaN`.

Special cases:

``notEqualWithin(+0.0, -0.0, epsilon) => false for any `epsilon >= 0.0`notEqualWithin(-0.0, +0.0, epsilon) => false for any `epsilon >= 0.0`notEqualWithin(+inf, +inf, epsilon) => false for any `epsilon >= 0.0`notEqualWithin(-inf, -inf, epsilon) => false for any `epsilon >= 0.0`notEqualWithin(x, NaN, epsilon)     => true for any x and `epsilon >= 0.0`notEqualWithin(NaN, y, epsilon)     => true for any y and `epsilon >= 0.0```

Example:

``import Float "mo:base/Float";let epsilon = 1e-6;Float.notEqualWithin(-12.3, -1.23e1, epsilon) // => false``

## Function `less`​

``func less(x : Float, y : Float) : Bool``

Returns `x < y`.

Special cases:

``less(+0.0, -0.0) => falseless(-0.0, +0.0) => falseless(NaN, y)     => false for any Float yless(x, NaN)     => false for any Float x``

Example:

``import Float "mo:base/Float";Float.less(Float.e, Float.pi) // => true``

## Function `lessOrEqual`​

``func lessOrEqual(x : Float, y : Float) : Bool``

Returns `x <= y`.

Special cases:

``lessOrEqual(+0.0, -0.0) => truelessOrEqual(-0.0, +0.0) => truelessOrEqual(NaN, y)     => false for any Float ylessOrEqual(x, NaN)     => false for any Float x``

Example:

``import Float "mo:base/Float";Float.lessOrEqual(0.123, 0.1234) // => true``

## Function `greater`​

``func greater(x : Float, y : Float) : Bool``

Returns `x > y`.

Special cases:

``greater(+0.0, -0.0) => falsegreater(-0.0, +0.0) => falsegreater(NaN, y)     => false for any Float ygreater(x, NaN)     => false for any Float x``

Example:

``import Float "mo:base/Float";Float.greater(Float.pi, Float.e) // => true``

## Function `greaterOrEqual`​

``func greaterOrEqual(x : Float, y : Float) : Bool``

Returns `x >= y`.

Special cases:

``greaterOrEqual(+0.0, -0.0) => truegreaterOrEqual(-0.0, +0.0) => truegreaterOrEqual(NaN, y)     => false for any Float ygreaterOrEqual(x, NaN)     => false for any Float x``

Example:

``import Float "mo:base/Float";Float.greaterOrEqual(0.1234, 0.123) // => true``

## Function `compare`​

``func compare(x : Float, y : Float) : {#less; #equal; #greater}``

Defines a total order of `x` and `y` for use in sorting.

Note: Using this operation to determine equality or inequality is discouraged for two reasons:

• It does not consider numerical errors, see comment above. Use `equalWithin(x, y, espilon)` or `notEqualWithin(x, y, epsilon)` to test for equality or inequality, respectively.
• `NaN` are here considered equal if their sign matches, which is different to the standard equality by `==` or when using `equal()` or `notEqual()`.

Total order:

• negative NaN (no distinction between signalling and quiet negative NaN)
• negative infinity
• negative numbers (including negative subnormal numbers in standard order)
• negative zero (`-0.0`)
• positive zero (`+0.0`)
• positive numbers (including positive subnormal numbers in standard order)
• positive infinity
• positive NaN (no distinction between signalling and quiet positive NaN)

Example:

``import Float "mo:base/Float";Float.compare(0.123, 0.1234) // => #less``

## Function `neg`​

``func neg(x : Float) : Float``

Returns the negation of `x`, `-x` .

Changes the sign bit for infinity.

Special cases:

``neg(+inf) => -infneg(-inf) => +infneg(+NaN) => -NaNneg(-NaN) => +NaNneg(+0.0) => -0.0neg(-0.0) => +0.0``

Example:

``import Float "mo:base/Float";Float.neg(1.23) // => -1.23``

## Function `add`​

``func add(x : Float, y : Float) : Float``

Returns the sum of `x` and `y`, `x + y`.

Note: Numerical errors may occur, see comment above.

Special cases:

``add(+inf, y)    => +inf if y is any Float except -inf and NaNadd(-inf, y)    => -inf if y is any Float except +inf and NaNadd(+inf, -inf) => NaNadd(NaN, y)     => NaN for any Float y``

The same cases apply commutatively, i.e. for `add(y, x)`.

Example:

``import Float "mo:base/Float";Float.add(1.23, 0.123) // => 1.353``

## Function `sub`​

``func sub(x : Float, y : Float) : Float``

Returns the difference of `x` and `y`, `x - y`.

Note: Numerical errors may occur, see comment above.

Special cases:

``sub(+inf, y)    => +inf if y is any Float except +inf or NaNsub(-inf, y)    => -inf if y is any Float except -inf and NaNsub(x, +inf)    => -inf if x is any Float except +inf and NaNsub(x, -inf)    => +inf if x is any Float except -inf and NaNsub(+inf, +inf) => NaNsub(-inf, -inf) => NaNsub(NaN, y)     => NaN for any Float ysub(x, NaN)     => NaN for any Float x``

Example:

``import Float "mo:base/Float";Float.sub(1.23, 0.123) // => 1.107``

## Function `mul`​

``func mul(x : Float, y : Float) : Float``

Returns the product of `x` and `y`, `x * y`.

Note: Numerical errors may occur, see comment above.

Special cases:

``mul(+inf, y) => +inf if y > 0.0mul(-inf, y) => -inf if y > 0.0mul(+inf, y) => -inf if y < 0.0mul(-inf, y) => +inf if y < 0.0mul(+inf, 0.0) => NaNmul(-inf, 0.0) => NaNmul(NaN, y) => NaN for any Float y``

The same cases apply commutatively, i.e. for `mul(y, x)`.

Example:

``import Float "mo:base/Float";Float.mul(1.23, 1e2) // => 123.0``

## Function `div`​

``func div(x : Float, y : Float) : Float``

Returns the division of `x` by `y`, `x / y`.

Note: Numerical errors may occur, see comment above.

Special cases:

``div(0.0, 0.0) => NaNdiv(x, 0.0)   => +inf for x > 0.0div(x, 0.0)   => -inf for x < 0.0div(x, +inf)  => 0.0 for any x except +inf, -inf, and NaNdiv(x, -inf)  => 0.0 for any x except +inf, -inf, and NaNdiv(+inf, y)  => +inf if y >= 0.0div(+inf, y)  => -inf if y < 0.0div(-inf, y)  => -inf if y >= 0.0div(-inf, y)  => +inf if y < 0.0div(NaN, y)   => NaN for any Float ydiv(x, NaN)   => NaN for any Float x``

Example:

``import Float "mo:base/Float";Float.div(1.23, 1e2) // => 0.0123``

## Function `rem`​

``func rem(x : Float, y : Float) : Float``

Returns the floating point division remainder `x % y`, which is defined as `x - trunc(x / y) * y`.

Note: Numerical errors may occur, see comment above.

Special cases:

``rem(0.0, 0.0) => NaNrem(x, y)     => +inf if sign(x) == sign(y) for any x and y not being +inf, -inf, or NaNrem(x, y)     => -inf if sign(x) != sign(y) for any x and y not being +inf, -inf, or NaNrem(x, +inf)  => x for any x except +inf, -inf, and NaNrem(x, -inf)  => x for any x except +inf, -inf, and NaNrem(+inf, y)  => NaN for any Float yrem(-inf, y)  => NaN for any Float yrem(NaN, y)   => NaN for any Float yrem(x, NaN)   => NaN for any Float x``

Example:

``import Float "mo:base/Float";Float.rem(7.2, 2.3) // => 0.3 (with numerical imprecision)``

## Function `pow`​

``func pow(x : Float, y : Float) : Float``

Returns `x` to the power of `y`, `x ** y`.

Note: Numerical errors may occur, see comment above.

Special cases:

``pow(+inf, y)    => +inf for any y > 0.0 including +infpow(+inf, 0.0)  => 1.0pow(+inf, y)    => 0.0 for any y < 0.0 including -infpow(x, +inf)    => +inf if x > 0.0 or x < 0.0pow(0.0, +inf)  => 0.0pow(x, -inf)    => 0.0 if x > 0.0 or x < 0.0pow(0.0, -inf)  => +infpow(x, y)       => NaN if x < 0.0 and y is a non-integral Floatpow(-inf, y)    => +inf if y > 0.0 and y is a non-integral or an even integral Floatpow(-inf, y)    => -inf if y > 0.0 and y is an odd integral Floatpow(-inf, 0.0)  => 1.0pow(-inf, y)    => 0.0 if y < 0.0pow(-inf, +inf) => +infpow(-inf, -inf) => 1.0pow(NaN, y)     => NaN if y != 0.0pow(NaN, 0.0)   => 1.0pow(x, NaN)     => NaN for any Float x``

Example:

``import Float "mo:base/Float";Float.pow(2.5, 2.0) // => 6.25``