Skip to content
Fixed-point numbers

Fixed-point numbers

Floating-point arithmetic can give slightly different answers on different processors, which is enough to make two runs of the same game drift apart. The engine uses fixed-point numbers instead: an int that counts in steps of 1/65536.

A fixed-point value is an ordinary int. The number 1.5 is stored as 98304, which is 1.5 times 65536. The compiler does not tell the two kinds of number apart, so keeping them straight is up to you.

fn main() -> int {
  let speed = fixed_from_ratio(3, 2);
  let time = fixed_from_ratio(5, 2);
  print(concat3("distance ", fixed_to_text(fixed_mul(speed, time)), "\n"))
}
bootstrap/qdx run std/*.qdx engine/*.qdx distance.qdx
distance 3.75

Functions

In engine/fixed.qdx.

FunctionResultMeaning
fixed_one()intThe value 1, which is 65536.
fixed_from_int(whole: int)intA whole number as fixed-point.
fixed_from_ratio(numerator: int, denominator: int)intThe fraction as fixed-point.
fixed_floor(a: int)intThe largest whole number not above a, as an ordinary int.
fixed_fraction(a: int)intWhat is left of a above its floor, from 0 to 65535.
fixed_mul(a: int, b: int)intThe product.
fixed_div(a: int, b: int)intThe quotient. Stops the program if b is zero.
fixed_to_text(a: int)bytesThe exact decimal value, always with a decimal point.

Adding and subtracting use the ordinary + and -. Multiplying or dividing a fixed-point value by an ordinary whole number uses * and /.

Rounding

A result that falls between two steps is rounded toward negative infinity, for both fixed_mul and fixed_div. This differs from / on ordinary numbers, which rounds toward zero, and it means rounding never changes direction as a value crosses zero.

Range

Whole parts reach about 140 trillion in either direction. fixed_mul gives the exact rounded product whenever that product fits and its second value is smaller than about two billion in size. Outside that it wraps around, as ordinary arithmetic does.

fixed_to_text prints every digit, so the smallest step reads 0.0000152587890625.