fixed

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2026 License: MIT Imports: 9 Imported by: 0

README

go-fixed

Go Reference

A signed 48.16 binary fixed-point numeric type for Go.

Why

Fixed-point arithmetic is deterministic across platforms and architectures - no floating-point rounding mode differences, no -ffast-math surprises. This library is built for applications like simulations and game logic where reproducibility matters more than decimal precision. If you need exact decimal fractions (e.g. finance), this is the wrong library.

Install

go get codeberg.org/firelizzard/go-fixed

Quick start

import "codeberg.org/firelizzard/go-fixed"

a := fixed.MustParse("1.5")
b := fixed.Float(2.25)
fmt.Println(a + b)          // 3.75
fmt.Println(a.Mul(b))       // 3.375
fmt.Println(a * 3)          // 4.5
fmt.Printf("%.2f\n", a)     // 1.50

Documentation

Overview

Package fixed implements a signed 48.16 binary fixed-point numeric type.

Representation & Precision

A Fixed value is stored as an int64 whose lower 16 bits represent the fractional part and upper 48 bits represent the signed integer part. This gives an integer range of roughly ±140 trillion with a fractional resolution of 1/65536 ≈ 0.0000153.

Because the representation is binary, not decimal, values like 0.1 cannot be stored exactly - the same tradeoff as float64 but with deterministic arithmetic and no rounding-mode surprises. Values that are exact sums of powers of two (0.5, 0.25, 0.125, …) are represented without error. The type is intended for applications that need deterministic fixed-point math (e.g. simulations, game logic) rather than exact decimal arithmetic (e.g. finance).

Arithmetic & Comparisons

Go's built-in operators fall into two groups when applied to Fixed values.

Operators that require both operands to be Fixed (to have the same scale): the additive operators (+, -), comparisons (<, <=, ==, !=, >=, >), and modulo (%). These work correctly when both operands are Fixed because the shared scale factor is a common term that distributes: (a·s) + (b·s) = (a+b)·s, and likewise for subtraction, comparison, and modulo.

Operators that require exactly one scaled and one unscaled operand: multiplication (*), division (/), and bit shifts (<<, >>). For multiplication the unscaled operand may be on either side since multiplication commutes; for division and shifts it must be on the right. These work because a single scale factor passes through: (a·s) * b = (a*b)·s and (a·s) / b = (a/b)·s. Multiplying or dividing two Fixed values with built-in operators produces a wrong result because the scale factors do not cancel: (a·s) * (b·s) = (a*b)·s², not (a*b)·s. Use the Fixed.Mul and Fixed.Div methods instead. There are no shift-by-Fixed methods since shifting by a fractional amount is not a meaningful operation.

Formatting

Formatting is delegated to math/big.Float via Fixed.Text, so all big.Float format verbs ('f', 'e', 'g', etc.) are supported. When used with fmt, the 'v' and 's' verbs produce decimal output ('f' format) and the default precision of -1 omits trailing zeros.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Fixed

type Fixed int64

Fixed is a signed 48.16 binary fixed-point number.

const (
	// Zero is the zero value.
	Zero Fixed = 0

	// One is the value 1.
	One Fixed = 1 << fBits
)

func Float

func Float(v float64) Fixed

Float converts a float64 to Fixed by truncating toward zero. It panics on NaN or overflow.

func Int

func Int(v int64, n int) Fixed

Int returns v / 10ⁿ as a Fixed. For example, Int(13, 1) returns 1.3 and Int(-25, 2) returns -0.25. A negative n multiplies by 10ⁿ instead: Int(1, -2) returns 100.

Int panics if n > 4 (higher decimal precision exceeds the fractional resolution) or if the result overflows.

func MustParse

func MustParse(s string) Fixed

MustParse is like Parse but panics on error.

func Parse

func Parse(s string) (Fixed, error)

Parse parses a decimal string into a Fixed value. It accepts optional leading '-' and an optional fractional part separated by '.'. Fractional digits beyond the 6th are silently truncated. Leading-dot forms like ".5" are accepted.

func (Fixed) Abs

func (v Fixed) Abs() Fixed

Abs returns the absolute value of v.

func (Fixed) Ceil

func (v Fixed) Ceil(n int) Fixed

Ceil returns v rounded up (toward +∞) to n decimal places. A negative n rounds to a power of 10. See Fixed.Round for a note on step size approximation.

func (Fixed) Div

func (v Fixed) Div(u Fixed) Fixed

Div returns v / u using 128-bit intermediate math to avoid overflow. The result is rounded to the nearest representable value (half-up). Div panics if u is zero.

func (Fixed) Float

func (v Fixed) Float() float64

Float converts v to a float64.

func (Fixed) Floor

func (v Fixed) Floor(n int) Fixed

Floor returns v rounded down (toward -∞) to n decimal places. A negative n rounds to a power of 10. See Fixed.Round for a note on step size approximation.

func (Fixed) Format

func (v Fixed) Format(s fmt.State, verb rune)

Format implements fmt.Formatter. The 'v' and 's' verbs produce decimal output ('f' format); 'f', 'e', 'E', 'g', 'G', and 'x' are passed through to big.Float.Text. An explicit precision (e.g. "%.4f") is honored; otherwise the default is -1 (shortest representation, trailing zeros removed). Unrecognized verbs produce a diagnostic string.

func (Fixed) Frac

func (v Fixed) Frac() float64

Frac returns the fractional part of v as a non-negative float64. For any v, v.Int() and v.Frac() satisfy:

v.Float() == float64(v.Int()) + v.Frac()  // when v >= 0
v.Float() == float64(v.Int()) - v.Frac()  // when v < 0

func (Fixed) Int

func (v Fixed) Int() int64

Int returns the integer part of v, truncated toward zero.

func (Fixed) MarshalJSON

func (v Fixed) MarshalJSON() ([]byte, error)

func (Fixed) Mul

func (v Fixed) Mul(u Fixed) Fixed

Mul returns v × u. It splits each operand into integer and fractional parts and cross-multiplies to avoid losing the fractional×fractional term. The result is exact when both operands are exact (e.g. binary fractions and integers); non-exact operands may lose up to 1 ULP.

func (Fixed) Round

func (v Fixed) Round(n int) Fixed

Round returns v rounded to n decimal places using half-up (away from zero) rounding. A negative n rounds to a power of 10: Round(-1) rounds to the nearest 10, Round(-2) to the nearest 100, etc.

The step size is computed as One.pow10(-n), which is exact for n ≤ 0 but an approximation for positive n due to the binary representation. As a result, rounding to decimal places is approximate—e.g. Round(2) uses a step of ≈0.01, not exactly 0.01.

func (Fixed) Sqrt

func (v Fixed) Sqrt() Fixed

Sqrt returns the square root of v using Newton's method, converging to within 1 ULP. It panics if v is negative.

func (Fixed) String

func (v Fixed) String() string

String returns v formatted as a decimal string with trailing zeros removed (equivalent to v.Text('f', -1)).

func (Fixed) Text

func (v Fixed) Text(format byte, prec int) string

Text formats v as a decimal string according to the given format and precision. It converts the underlying representation to a big.Rat and delegates to big.Float.Text, so all format bytes accepted by big.Float ('f', 'e', 'g', etc.) are supported. A precision of -1 produces the shortest representation with no trailing zeros.

Rounding follows big.Float semantics (round-to-even / banker's rounding).

func (*Fixed) UnmarshalJSON

func (v *Fixed) UnmarshalJSON(b []byte) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL