frac4

package module
v0.0.0-...-498be49 Latest Latest
Warning

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

Go to latest
Published: Mar 20, 2026 License: MIT Imports: 7 Imported by: 0

README

frac4

A tiny Go package for storing fractional numbers in the range 0.0000 .. 1.0000 using a compact, exact fixed-point representation with 4 fractional digits.

Internally, values are stored as a uint16 scaled by 10,000:

realValue = scaled / 10000

So every representable value maps exactly to 2 bytes on disk/wire.

Installation

go get github.com/aszxqaz/frac4

Package overview

Types
  • type Value uint16: a quantized fraction with 4 decimal digits, representing numbers in [0.0000, 1.0000].
Constants
  • frac4.Scale (10000): the scaling factor.
  • frac4.Max (10000): the maximum scaled value (represents 1.0000).

API

Construction
func FromScaled(s uint16) (Value, error)
func MustFromScaled(s uint16) Value
func FromFloat64(x float64) (Value, error)
func Parse(s string) (Value, error)
  • Prefer Parse (string) or FromScaled (integer) when you need exact decimal semantics at the 1e-4 grid.
  • FromFloat64 and JSON number inputs are rounded to the nearest 1e-4 using float math (see Caveats).
Formatting / conversion
func (v Value) Scaled() uint16
func (v Value) Float64() float64
func (v Value) StringFixed4() string
func (v Value) StringShort() string
func (v Value) String() string
  • StringFixed4() always prints exactly 4 fractional digits (e.g. 0.1200, 1.0000).
  • StringShort() trims trailing zeros (e.g. 0.1200 -> 0.12, 1.0000 -> 1).
Encoding

The package implements these encoding interfaces for convenient transport/storage:

  • encoding.BinaryMarshaler / encoding.BinaryUnmarshaler
  • encoding.TextMarshaler / encoding.TextUnmarshaler
  • encoding/json (MarshalJSON / UnmarshalJSON)
Binary encoding (2 bytes)
  • MarshalBinary() encodes the underlying uint16 as 2 bytes in little-endian order.
  • Example: you can store Value directly in a compact binary stream.
JSON encoding
  • MarshalJSON() emits a JSON string like "0.1200" so the 1e-4 precision is preserved exactly.
  • UnmarshalJSON() accepts either:
    • a JSON string (preferred): "0.1200" parsed exactly, or
    • a JSON number (approximate): 0.00005 is rounded to the nearest 1e-4.

Example usage

Parse from a decimal string (exact)
package main

import (
	"fmt"

	"github.com/aszxqaz/frac4"
)

func main() {
	v, err := frac4.Parse("0.1200")
	if err != nil {
		panic(err)
	}

	fmt.Println(v.Scaled())       // 1200
	fmt.Println(v.StringFixed4()) // 0.1200
	fmt.Println(v.StringShort()) // 0.12
}
Binary round-trip
package main

import (
	"fmt"

	"github.com/aszxqaz/frac4"
)

func main() {
	v := frac4.MustFromScaled(9876) // 0.9876

	b, err := v.MarshalBinary()
	if err != nil {
		panic(err)
	}

	var decoded frac4.Value
	if err := decoded.UnmarshalBinary(b); err != nil {
		panic(err)
	}

	fmt.Println(decoded.StringFixed4()) // 0.9876
}
JSON
package main

import (
	"encoding/json"
	"fmt"

	"github.com/aszxqaz/frac4"
)

func main() {
	v, _ := frac4.Parse("0.1200")

	b, _ := json.Marshal(v)
	fmt.Println(string(b)) // "0.1200"

	var w frac4.Value
	_ = json.Unmarshal([]byte(`"0.0005"`), &w) // exact from string

	var x frac4.Value
	_ = json.Unmarshal([]byte(`0.00005`), &x) // rounds to 0.0001
}

Caveats (important)

Float inputs are approximate

This package stores values exactly as a fixed-point uint16. However, if you start from a float64 (or JSON numbers), the conversion uses float math and then rounds to the nearest 1e-4. Because floats are approximate, you may get an adjacent representable value around rounding boundaries.

If you need deterministic 1e-4 behavior, use:

  • Parse("0.1234") for decimal strings, or
  • FromScaled(1234) for integer scaled inputs.
Allowed range

Value is only valid for [0.0000, 1.0000] (scaled [0, 10000]).

Parsing rules

Parse accepts decimal strings like:

  • 0, 1
  • 0.1, 0.12, 0.1234
  • 1., 0.
  • .1234

It rejects:

  • negative values
  • more than 4 digits after the decimal point
  • malformed formats (non-digits where digits are expected)

License

MIT. See LICENSE.

Documentation

Overview

Package frac4 stores fractional values in the range [0.0000, 1.0000] using a compact fixed-point representation with 4 decimal digits.

The value is encoded as an integer scaled by 10,000, so each value is exactly represented with 4 fractional digits.

Index

Constants

View Source
const (
	// Scale turns 0.0000..1.0000 into 0..10000 (inclusive).
	Scale uint16 = 10000
	// Max is the maximum scaled value (representing 1.0000).
	Max uint16 = 10000
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Value

type Value uint16

Value stores a number in [0.0000, 1.0000] with exactly 4 decimal places.

It is represented as an integer v where realValue = v / 10000.

func FromFloat64

func FromFloat64(x float64) (Value, error)

FromFloat64 converts an approximate float in [0..1] by rounding to the nearest 1e-4 (four fractional digits).

func FromScaled

func FromScaled(s uint16) (Value, error)

FromScaled constructs a Value from its underlying scaled integer. The input must be in [0..10000].

func MustFromScaled

func MustFromScaled(s uint16) Value

MustFromScaled is FromScaled but panics on invalid input.

func Parse

func Parse(s string) (Value, error)

Parse parses decimals like "0.000", "0.12", "0.1234", "1", "1.0000" (up to 4 fractional digits).

The returned value is always quantized to exactly 4 digits.

func (Value) Float64

func (v Value) Float64() float64

Float64 returns the value as a float64.

Note: floats may not represent the value exactly, so prefer parsing from strings (or using FromScaled) when exact decimal semantics matter.

func (Value) MarshalBinary

func (v Value) MarshalBinary() ([]byte, error)

MarshalBinary encodes the value as 2 little-endian bytes.

func (Value) MarshalJSON

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

MarshalJSON encodes as a JSON string to preserve exact 1e-4 precision.

func (Value) MarshalText

func (v Value) MarshalText() ([]byte, error)

MarshalText encodes as the fixed4 decimal string form.

func (Value) Scaled

func (v Value) Scaled() uint16

Scaled returns the underlying integer in [0..10000].

func (Value) String

func (v Value) String() string

func (Value)