A fixed-point decimal number with precision decimal places.
The underlying representation is a scaled integer: $$\text{Fixed}_p(v) \equiv v \times 10^{-p}$$
The precision $p$ is a type parameter, so Fixed 2 $\neq$ Fixed 4.
This prevents accidental mixing of different precisions at compile time.
For example, Fixed 2 represents values like $3.14$ (stored as $314$).
- raw : Int
The raw scaled integer. The actual value is $\text{raw} \times 10^{-\text{precision}}$.
Instances For
Equations
- Data.instBEqFixed = { beq := Data.instBEqFixed.beq }
Equations
- Data.instOrdFixed.ord { raw := a } { raw := b } = (compare a b).then Ordering.eq
Instances For
Equations
- Data.instOrdFixed = { compare := Data.instOrdFixed.ord }
Equations
- Data.instReprFixed.repr x✝ prec✝ = Std.Format.bracket "{ " (Std.Format.nil ++ Std.Format.text "raw" ++ Std.Format.text " := " ++ (Std.Format.nest 7 (repr x✝.raw)).group) " }"
Instances For
Equations
- Data.instReprFixed = { reprPrec := Data.instReprFixed.repr }
Equations
Compute $10^n$ as a natural number. Helper for scaling operations. $$\text{scale}(p) = 10^p$$
Equations
- Data.Fixed.scale p = Nat.pow 10 p
Instances For
Create a Fixed from an integer (no fractional part).
$$\text{fromInt}(n) = n \times 10^p \times 10^{-p} = n$$
Equations
- Data.Fixed.fromInt n = { raw := n * ↑(Data.Fixed.scale p) }
Instances For
Addition of fixed-point numbers (exact, no precision loss): $$\text{Fixed}_p(a) + \text{Fixed}_p(b) = \text{Fixed}_p(a + b)$$
Equations
- Data.Fixed.instAdd = { add := fun (a b : Data.Fixed p) => { raw := a.raw + b.raw } }
Subtraction of fixed-point numbers (exact, no precision loss): $$\text{Fixed}_p(a) - \text{Fixed}_p(b) = \text{Fixed}_p(a - b)$$
Equations
- Data.Fixed.instSub = { sub := fun (a b : Data.Fixed p) => { raw := a.raw - b.raw } }
Negation: $-\text{Fixed}_p(a) = \text{Fixed}_p(-a)$.
Equations
- Data.Fixed.instNeg = { neg := fun (a : Data.Fixed p) => { raw := -a.raw } }
Multiplication scales by $10^{-p}$ to maintain precision: $$\text{Fixed}_p(a) \times \text{Fixed}_p(b) = \text{Fixed}_p\!\left(\left\lfloor \frac{a \cdot b}{10^p} \right\rfloor\right)$$
Note: multiplication may lose precision in the last digit due to truncation.
Equations
- Data.Fixed.instMul = { mul := fun (a b : Data.Fixed p) => { raw := a.raw * b.raw / ↑(Data.Fixed.scale p) } }
Equations
- Data.Fixed.instOfNatOfNatNat_1 = { ofNat := { raw := ↑(Data.Fixed.scale p) } }
Equations
- Data.Fixed.instInhabited = { default := 0 }
Equations
- One or more equations did not get rendered due to their size.
Addition is exact: adding two fixed-point values and converting to ratio equals converting each to ratio and adding.
$$\text{toRatio}(a + b) = \text{toRatio}(a) + \text{toRatio}(b)$$
This is the key advantage of fixed-point over floating-point: addition introduces no rounding error.
Convert to a Ratio preserving the exact value:
$$\text{toRatio}(\text{Fixed}_p(v)) = \frac{v}{10^p}$$
Equations
- f.toRatio = Data.Ratio.mk' f.raw ↑(Data.Fixed.scale p) ⋯