LEVIATHAN v962456e · 962456eee1

Standard Library

class float

A 64-bit IEEE 754 floating-point number (binary64).

since 0.1.0-alpha.1linuxwindowswasm

Overview

A literal with a decimal point (2.0) is a float. A float prints with six digits after the decimal point, and the special values print as nan, inf and -inf. Arithmetic follows IEEE 754: an operation such as the square root of a negative number produces nan, and an overflow produces inf, instead of throwing. Use isNaN and isInfinite to test for them; a comparison such as x == float::NaN is never true.

Mixed arithmetic is promoted: an int combined with a float gives a float. To go back to an int call toInt, which truncates. The narrower formats float8, float16 and float32 are reached with toFloat8, toFloat16 and toFloat32.

Description

float is an IEEE 754 binary64 number and the type of any literal with a decimal point. It is a value type. There is no exponent notation in literals: write 1000.0, not 1e3.

A float always prints with six digits after the point. Infinities print as inf and -inf, negative zero as -0.000000, and every NaN prints as nan, whatever its internal bits.

Rounding, printing and special values

float x = 3.5;
console.writeln(x);
console.writeln(x.floor());
console.writeln(x.ceil());
console.writeln(x.round());
console.writeln((-2.5).round());
console.writeln(x.trunc());
console.writeln((-3.99).toInt());
console.writeln(2.0.sqrt());
console.writeln((-1.0).sqrt());
console.writeln(0.1 + 0.2 == 0.3);
console.writeln(0.1 + 0.2);
console.writeln(1000000.0 * 1000000.0);
float zero = 0.0;
console.writeln(1.0 / zero);
console.writeln(-1.0 / zero);
console.writeln(zero / zero);
console.writeln(-zero);
try {
    console.writeln((1.0 / zero).toInt());
} catch (RuntimeException e) {
    console.writeln("caught: ${e.message}");
}
3.500000
3.000000
4.000000
4.000000
-3.000000
3.000000
-3
1.414214
nan
false
0.300000
1000000000000.000000
inf
-inf
nan
-0.000000
caught: float is not finite or out of int64 range for toInt()

Rules

  • Arithmetic follows IEEE 754. Division by zero gives infinity (or NaN for 0.0 / 0.0) rather than throwing.
  • round() rounds halves away from zero. sqrt() of a negative number is NaN, not an error.
  • toInt() truncates toward zero. It throws a catchable RuntimeException for NaN, an infinity or a value outside the int range.
  • A bare == between two floats is the IEEE operator: NaN == NaN is false, and -0.0 == 0.0 is true.
  • Where equality is derived or a value is used as a key, floats compare by the canonical relation instead: every NaN equals every NaN, and -0.0 equals 0.0. That relation applies to the == a struct gets automatically, to Map keys, and to match arms. canonEq is the same relation as a method.
  • A match arm can test for NaN with float::NaN.
  • If you write your own == for a struct, it means exactly what you wrote: floats inside it compare with the IEEE operators.
  • bits() returns the raw 64-bit pattern as an int, and float::fromBits(n) builds a float from one. A pattern you construct round-trips exactly. The bits of a NaN produced by arithmetic are not specified.
  • string.toFloat() parses finite decimal numbers only and returns None for anything else, including "inf" and "nan".

Examples

Canonical equality for NaN, in keys, structs and match:

IEEE equality versus the canonical relation

struct Reading {
    float v = 0.0;
}

void classify(float f) {
    match (f) {
        float::NaN => console.writeln("not a number");
        else => console.writeln("a number");
    }
}

float zero = 0.0;
float nan = zero / zero;
Reading a = Reading(nan);
Reading b = Reading(nan);
console.writeln(nan == nan);
console.writeln(a == b);
console.writeln(zero == -zero);
console.writeln(nan.canonEq(nan));
Map<float, int> m = Map();
m[nan] = 1;
m[nan] = 2;
console.writeln(m.length());
classify(nan);
classify(1.5);
false
true
true
true
1
not a number
a number

Notes

The narrow formats float8, float16 and float32 are described in lang.sized-floats.

Examples

Typical use

float price = 19.99;
float total = price * 3.0;
console.writeln(total);
console.writeln(total.round());
console.writeln(total.toInt());
console.writeln((0.0 - total).abs());
float bad = (0.0 - 1.0).sqrt();
console.writeln(bad.isNaN());
console.writeln("total: ${total}");
59.970000
60.000000
59
59.970000
true
total: 59.970000

Methods

abs

abs() -> float

The absolute value: this with any minus sign removed.

A NaN stays a NaN.

Returns

this if it is zero or positive, otherwise its negation.

Examples

console.writeln((0.0 - 3.7).abs());
console.writeln(3.7.abs());
console.writeln(float::NaN.abs().isNaN());
3.700000
3.700000
true

bits

bits() -> int

The raw IEEE 754 binary64 bit pattern, as an int.

Useful for serialization and for inspecting a value exactly. float::fromBits is the inverse. The bits of a NaN produced by arithmetic (rather than written as float::NaN) are not specified and can differ between engines and targets, so do not compare them.

Returns

The 64 bits of this, reinterpreted as a signed int.

Examples

console.writeln(1.0.bits());
console.writeln(1.0.bits().toHex());
console.writeln(float::fromBits(4611686018427387904));
console.writeln(float::fromBits(1.5.bits()) == 1.5);
4607182418800017408
3ff0000000000000
2.000000
true

See also: canonEq

canonEq

canonEq(float other) -> bool

Compare two floats under the canonical relation used for struct equality, Map keys and match.

The ordinary == is the IEEE comparison, where NaN is not equal to itself and -0.0 equals 0.0. Under canonEq every NaN equals every other NaN, while -0.0 still equals 0.0. This is also how a struct with a float field decides whether two values are equal.

Parameters

other
The value to compare with.

Returns

true if the two values are the same under the canonical relation.

Examples

float nan = float::NaN;
console.writeln(nan == nan);
console.writeln(nan.canonEq(nan));
console.writeln(1.5.canonEq(1.5));
console.writeln(1.5.canonEq(2.5));
false
true
true
false

See also: isNaN

ceil

ceil() -> float

Round up to the nearest whole number that is not less than this.

The result is still a float. Negative numbers round toward zero (-2.5 becomes -2.0).

Returns

The smallest whole-valued float greater than or equal to this.

Examples

console.writeln(2.1.ceil());
console.writeln((0.0 - 2.9).ceil());
console.writeln(5.0.ceil());
3.000000
-2.000000
5.000000

See also: floor, round, trunc

floor

floor() -> float

Round down to the nearest whole number that is not greater than this.

The result is still a float; call toInt to get an int. Negative numbers round away from zero (-2.5 becomes -3.0).

Returns

The largest whole-valued float less than or equal to this.

Examples

console.writeln(2.9.floor());
console.writeln((0.0 - 2.1).floor());
console.writeln(5.0.floor());
2.000000
-3.000000
5.000000

See also: ceil, round, trunc

isInfinite

isInfinite() -> bool

Test whether the value is positive or negative infinity.

Infinity results from overflow, for example 10.0.pow(400.0). A NaN is not infinite.

Returns

true if this is inf or -inf.

Examples

float big = 10.0.pow(400.0);
console.writeln(big);
console.writeln(big.isInfinite());
console.writeln((0.0 - big).isInfinite());
console.writeln(1.0.isInfinite());
console.writeln(float::NaN.isInfinite());
inf
true
true
false
false

See also: isNaN

isNaN

isNaN() -> bool

Test whether the value is NaN ("not a number").

NaN results from operations such as the square root of a negative number. It is the only value that is not equal to itself, which is why x == float::NaN is useless and isNaN exists.

Returns

true if this is NaN.

Examples

float r = (0.0 - 1.0).sqrt();
console.writeln(r.isNaN());
console.writeln(r == r);
console.writeln(1.0.isNaN());
true
false
false

See also: isInfinite, canonEq

pow

pow(float e) -> float

Raise this to a power.

Follows the C pow function: a result too large to represent is inf, and a negative base with a fractional exponent is NaN.

Parameters

e
The exponent.

Returns

this raised to the power e.

Examples

console.writeln(2.0.pow(10.0));
console.writeln(9.0.pow(0.5));
console.writeln(2.0.pow(0.0 - 1.0));
console.writeln(10.0.pow(400.0));
1024.000000
3.000000
0.500000
inf

See also: sqrt

round

round() -> float

Round to the nearest whole number, with halves rounded away from zero.

2.5 becomes 3.0 and -2.5 becomes -3.0, as in the C round function; this is not banker's rounding. The result is still a float.

Returns

The nearest whole-valued float.

Examples

console.writeln(2.4.round());
console.writeln(2.5.round());
console.writeln((0.0 - 2.5).round());
console.writeln(3.5.round());
2.000000
3.000000
-3.000000
4.000000

See also: floor, ceil, trunc

sqrt

sqrt() -> float

The square root.

A negative number gives NaN rather than throwing; test the result with isNaN.

Returns

The non-negative square root of this, or NaN if this is negative.

Examples

console.writeln(16.0.sqrt());
console.writeln(2.0.sqrt());
float r = (0.0 - 4.0).sqrt();
console.writeln(r.isNaN());
4.000000
1.414214
true

See also: pow

toFloat16

toFloat16() -> float16

Convert to the 16-bit float16 format (IEEE binary16).

The value is rounded to the nearest representable one, ties to even. The conversion throws when a finite value is too large for the format (the largest finite float16 is 65504); an infinity converts to an infinity and a NaN to the NaN.

Returns

The nearest float16.

Throws

RuntimeException
when this is finite but outside the range of float16.

Examples

float16 a = 0.1.toFloat16();
console.writeln(a.toFloat());
try {
    console.writeln(70000.0.toFloat16());
} catch (RuntimeException e) {
    console.writeln("caught: ${e.message}");
}
0.099976
caught: toFloat16: value out of range (max finite 65504)

See also: float16, toFloat8, toFloat32

toFloat32

toFloat32() -> float32

Convert to the 32-bit float32 format (IEEE binary32).

The value is rounded to the nearest representable one, ties to even, so precision beyond about seven decimal digits is lost. The conversion throws when a finite value is too large for the format (the largest finite float32 is about 3.4e38).

Returns

The nearest float32.

Throws

RuntimeException
when this is finite but outside the range of float32.

Examples

float32 a = 0.1.toFloat32();
console.writeln(a.toFloat());
console.writeln(a.toFloat() == 0.1);
console.writeln(a.toFloat().bits() == 0.1.bits());
0.100000
false
false

See also: float32, toFloat8, toFloat16

toFloat8

toFloat8() -> float8

Convert to the 8-bit float8 format (E4M3).

The value is rounded to the nearest representable one, ties to even. The conversion throws instead of overflowing: float8 has no infinity, so a value beyond its finite range cannot be represented. A NaN converts to the float8 NaN.

Returns

The nearest float8.

Throws

RuntimeException
when this is infinite or finite but too large for float8 (the largest finite value is 448).

Examples

float8 a = 1.5.toFloat8();
console.writeln(a.toFloat());
try {
    console.writeln(1000.0.toFloat8());
} catch (RuntimeException e) {
    console.writeln("caught: ${e.message}");
}
1.500000
caught: toFloat8: value out of range (max finite 448)

See also: float8, toFloat16, toFloat32

toInt

toInt() -> int

Convert to an int by dropping the fractional part (rounding toward zero).

Throws instead of returning a wrong number when there is no int to return.

Returns

The truncated value as an int.

Throws

RuntimeException
when this is NaN, infinite, or outside the range of a 64-bit int.

Examples

console.writeln(3.99.toInt());
console.writeln((0.0 - 3.99).toInt());
console.writeln(2.5.round().toInt());
try {
    console.writeln(float::NaN.toInt());
} catch (RuntimeException e) {
    console.writeln("caught: ${e.message}");
}
3
-3
3
caught: float is not finite or out of int64 range for toInt()

See also: trunc, round

toString

toString() -> string

Format the number as text, with six digits after the decimal point.

The result is also what string concatenation and ${} interpolation produce. A NaN is always spelled nan, and the infinities inf and -inf. Negative zero prints as -0.000000.

Returns

The decimal text of this.

Examples

console.writeln(3.5.toString());
console.writeln(0.1 + 0.2);
console.writeln(float::NaN.toString());
console.writeln((0.0 - 1.0).sqrt().toString());
string s = "value=" + 2.0.toString();
console.writeln(s);
3.500000
0.300000
nan
nan
value=2.000000

trunc

trunc() -> float

Drop the fractional part, rounding toward zero.

Unlike floor, a negative number is not rounded down: -3.99 becomes -3.0. The result is still a float; use toInt for an int.

Returns

this without its fractional part.

Examples

console.writeln(3.99.trunc());
console.writeln((0.0 - 3.99).trunc());
console.writeln((0.0 - 3.99).floor());
3.000000
-3.000000
-4.000000

See also: floor, ceil, round, toInt

See also

  • int — The signed 64-bit integer type, the default type of whole numbers.
  • Sized floats: float8, float16, float32 — The narrow floating-point formats, how every operation re-rounds, and where they overflow or throw.
  • Numeric conversions and working types — How operands of different numeric types combine, and when a value is converted on its way into a typed variable, field, parameter or return.