decint

package
v1.148.0 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package decint provides utility functions to parse and represent decimal values as fixed-point integers with a defined precision.

This package solves the common problem of safely handling small monetary and fixed-precision decimal values without using floating-point arithmetic for storage or comparison.

Decint is designed for values with at most six decimal places, and it stores those values as integers (scaled by 1e6) to preserve deterministic behavior in comparisons, serialization, and transport.

Top features:

- bidirectional conversion between float64/string and scaled int64 or uint64 - fixed six-decimal output formatting for stable text representation - explicit parse errors for invalid numeric strings - published safe range constants (MaxInt and MaxFloat) for boundary checks - unsigned conversion helpers that clamp non-positive values to zero

Implementation note:

  • float-to-integer conversion scales by 1e6 and rounds to the nearest integer (half away from zero), so extra fractional digits beyond the supported precision are rounded rather than truncated.

Key benefits:

- deterministic decimal handling for currency, rates, and small amounts - exact six-decimal representation for every value within the safe range

Safe range:

  • Values are safe up to MaxFloat = 2^33 = 8_589_934_592 with six exact decimal places. This is the largest magnitude at which a float64 still resolves a 1e-6 step (its ULP stays below 1e-6); beyond it the sixth decimal digit is no longer representable, so it is intentionally excluded from the safe range rather than silently rounded.

Index

Examples

Constants

View Source
const (

	// MaxInt is the maximum scaled integer that preserves six exact decimals
	// (2^33 * 1e6). It is below 2^53, so it is still an exact float64.
	MaxInt = 8_589_934_592_000_000

	// MaxFloat is the maximum value that preserves six exact decimals in a
	// float64 (2^33). Above it the float64 ULP exceeds 1e-6 and the sixth
	// decimal digit can no longer be represented.
	MaxFloat = 8_589_934_592
)

Variables

View Source
var (
	// ErrInvalidNumber indicates the input string is not a valid finite number.
	ErrInvalidNumber = errors.New("invalid decimal number")

	// ErrOutOfRange indicates the value is outside the safe range.
	ErrOutOfRange = errors.New("value out of safe range")
)

Functions

func FloatToInt

func FloatToInt(v float64) int64

FloatToInt converts a decimal float into the scaled int64 fixed-point form.

The value is multiplied by 1e6 and rounded to the nearest integer (half away from zero), so exact decimal inputs whose float64 form is one ULP off (e.g. 8.2) still map to their exact scaled value.

Non-finite and out-of-range inputs are clamped (the signature is preserved): NaN yields 0, +Inf or values above MaxFloat yield MaxInt, and -Inf or values below -MaxFloat yield -MaxInt.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v := decint.FloatToInt(123.456)

	fmt.Println(v)

}
Output:
123456000

func FloatToUint

func FloatToUint(v float64) uint64

FloatToUint converts a decimal float into the scaled uint64 fixed-point form.

The value is multiplied by 1e6 and rounded to the nearest integer (half away from zero), so exact decimal inputs whose float64 form is one ULP off (e.g. 8.2) still map to their exact scaled value.

Values less than or equal to zero are clamped to 0, making this helper safe for unsigned amount domains.

Non-finite and out-of-range inputs are clamped (the signature is preserved): NaN and values less than or equal to zero (including -Inf) yield 0, while +Inf or values above MaxFloat yield MaxInt.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v := decint.FloatToUint(123.456)

	fmt.Println(v)

}
Output:
123456000

func IntToFloat

func IntToFloat(v int64) float64

IntToFloat converts a scaled int64 fixed-point value back to float64.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v := decint.IntToFloat(123456)

	fmt.Println(v)

}
Output:
0.123456

func IntToString

func IntToString(v int64) string

IntToString formats a scaled int64 value as a six-decimal string.

The value is formatted directly from the integer, so the output is exact for every int64 (including values outside the safe range) and independent of float64 precision.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v := decint.IntToString(123456)

	fmt.Println(v)

}
Output:
0.123456

func StringToInt

func StringToInt(s string) (int64, error)

StringToInt parses a decimal string and returns its scaled int64 form.

This is useful when ingesting textual values from config, APIs, or storage while preserving the package's fixed-point representation.

Unlike FloatToInt, which clamps non-finite and out-of-range values, this function returns an error wrapping ErrInvalidNumber when the string cannot be parsed or is NaN or infinite, and ErrOutOfRange when the value is outside the safe range [-MaxFloat, MaxFloat].

Example
package main

import (
	"fmt"
	"log"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v, err := decint.StringToInt("123456")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(v)

}
Output:
123456000000

func StringToUint

func StringToUint(s string) (uint64, error)

StringToUint parses a decimal string and returns its scaled uint64 form.

The rules mirror the unsigned domain:

  • a string that cannot be parsed, or that is NaN or infinite (either sign), returns an error wrapping ErrInvalidNumber;
  • a finite value less than or equal to zero is clamped to 0 (no error);
  • a finite value above MaxFloat returns an error wrapping ErrOutOfRange.
Example
package main

import (
	"fmt"
	"log"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v, err := decint.StringToUint("123.456")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(v)

}
Output:
123456000

func UintToFloat

func UintToFloat(v uint64) float64

UintToFloat converts a scaled uint64 fixed-point value back to float64.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v := decint.UintToFloat(123456)

	fmt.Println(v)

}
Output:
0.123456

func UintToString

func UintToString(v uint64) string

UintToString formats a scaled uint64 value as a six-decimal string.

The value is formatted directly from the integer, so the output is exact for every uint64 (including values outside the safe range) and independent of float64 precision.

Example
package main

import (
	"fmt"

	"github.com/tecnickcom/nurago/pkg/decint"
)

func main() {
	v := decint.UintToString(123456)

	fmt.Println(v)

}
Output:
0.123456

Types

This section is empty.

Jump to

Keyboard shortcuts

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