# How could fixed-point be implemented?

Fixed point is essentially storing a number of units of a certain size instead of storing a significand and an exponent. However, if the units could be of any size, how big would the fixed-point units be in a typical fixed type of a programming language? C does not have fixed-point, so to use this one just stores an integer and divides by the number of units in a 1 to get the value, for example, one could store an angle as a uint16_t x; representing 65536ths of a turn, and call sinpif(x*0x1p-15F). However, if a language were to implement proper fixed-point semantics, how could this be done? What would be a typical range and precision of the varying fixed-point types?

Fixed-point is an integer with a statically-known decimal (or more generally, statically-known divisor). You can represent a fixed-point datatype as an "representation" integer type and "divisor" integer (kind of like a fixed-sized array, which is an "element" type and statically-known "length" integer). At runtime, the value is simply an integer, but the compiler uses the statically-known divisor to do proper conversion (e.g. to floating-point or string).

For example, imagine a language with this syntax

type Currency = FixedPoint<u32, 100>

let currency1: Currency = 50.34  # represented as 5034
let currency2: Currency = 123.9  # represented as 12390
let currency3: Currency = currency1 + currency2  # represented as 17424
print(currency3)  # prints 174.24


Note that there isn't one "fixed-point" type, since different types may opt for different fixed points. The key difference between these types and a floating-point type, is that all instances of a particular fixed point type have the same "decimal" or divisor (whereas floating-points the decimal can be at different points at runtime).

I actually don't know any real-world languages which implement this feature, though. The closest may be F#, which has measurement types. For your specific example, you could declare a [<Measure>] type angle, and then ensure that int16<angle> n is treated as n 2*pi/65536 radians like so:

[<Measure>] type angle

let toRadians (x: int16<angle>) = x * 2 * pi / 65536<angle>


Then you can't use int16<angle> wherever a unit type is expected, you must apply toRadians first.

• For real-world uses of fixed-point arithmetic, a good place to look is probably assembly languages for digital signal processing chips. Fixed point numbers are used a lot in DSP. Commented May 20, 2023 at 19:12
• COBOL has fixed-point arithmetic. The reason some programmers care about fixed-point arithmetic is that it's used in the real world! Commented May 20, 2023 at 20:50

# Make precision part of the type

I’m not familiar with any general-purpose languages that use fixed point at all, but this is what PostgreSQL does. If you want to indicate that a column stores 15 digits, of which two are to the right of the decimal point, type it as NUMERIC(15, 2). This way, each user can choose a reasonable scale for their application, instead of the language forcing one on them.

# Have a default precision, and allow changing it

Lisp has several different types of floats. One is long-float, with arbritrary precision. For example:

(SETF (EXT:LONG-FLOAT-DIGITS) 3322)


This sets the "long float" precision to 3322 binary digits (approximately 1000 decimal digits). By default, it's 64 binary digits.

After this, you can print out a long float to see that it works: Try it online!

# GCC Fixed-Point Types

GCC has fixed point types as an extension. The types are _Fract and _Accum (A new language would designate them as just fract and accum) and could be combined with long short etc to specify precision, and unsigned to specify signedness.

## fract

A fract would store a normalized value between [0, 1). The increments would be 1/2^bits where bits is bits of precision. If signed, one of the bits would be a sign bit so the increments would be twice as big.

## accum

An accum would store half the bits as integer bits and half as fraction bits. The range would be [0, 2^(bits/2)) but in increments of 1/2^(bits/2).

The given examples are

type Volt is delta 0.125 range 0.0 .. 255.0;

-- A pure fraction which requires all the available
-- space in a word can be declared as the type Fraction:
type Fraction is delta System.Fine_Delta range -1.0 .. 1.0;
-- Fraction'Last = 1.0 – System.Fine_Delta

type Money is delta 0.01 digits 15;  -- decimal fixed point
subtype Salary is Money digits 10;
-- Money'Last = 10.0**13 – 0.01, Salary'Last = 10.0**8 – 0.01


There's two alternatives; a normal fixed-point type uses a power of two as its delta, and a decimal fixed-point type uses a power of ten.

• The question is not what languages have fixed point but how you might implement it for your own language Commented May 20, 2023 at 19:17
• @mousetail This shows the same details as the Lisp and SQL examples above. They're all examples of how the syntax could work, and certainly for binary fixed-point, the implementations pretty trivial; shift everything by the appropriate power of two on literals and conversions, don't worry about add and subtract, and do the obvious modifications on multiply and divide. Commented May 20, 2023 at 19:21