Math #

Numeric computation is everywhere — calculating discounts, generating random numbers, validating geographic coordinates, processing statistical data, and implementing cryptographic algorithms. Go provides the math package in the standard library covering all common mathematical needs: important constants, trigonometric functions, logarithms, exponents, rounding, and the boundary values of numeric types. Beyond that, Go also provides math/rand for random numbers and math/big for arbitrary-precision arithmetic when float64 and int64 are no longer enough. This article covers the entire math package ecosystem in Go — how it works, when to use it, and the numeric pitfalls to watch out for.

Mathematical Constants #

The math package defines the important constants often needed in scientific and engineering computation. All these constants are float64 with full precision.

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println(math.Pi)      // 3.141592653589793   — π
    fmt.Println(math.E)       // 2.718281828459045   — Euler's number
    fmt.Println(math.Phi)     // 1.618033988749895   — golden ratio φ
    fmt.Println(math.Sqrt2)   // 1.4142135623730951  — √2
    fmt.Println(math.SqrtE)   // 1.6487212707001282  — √e
    fmt.Println(math.Log2E)   // 1.4426950408889634  — log₂(e)
    fmt.Println(math.Log10E)  // 0.4342944819032518  — log₁₀(e)
    fmt.Println(math.Ln2)     // 0.6931471805599453  — ln(2)
}

Besides mathematical constants, math also defines the boundary values for Go’s numeric types:

// Maximum and minimum float64 values
fmt.Println(math.MaxFloat64)    // 1.7976931348623157e+308
fmt.Println(math.SmallestNonzeroFloat64) // 5e-324

// Maximum integer values (useful for minimum-search algorithms)
fmt.Println(math.MaxInt8)   // 127
fmt.Println(math.MaxInt16)  // 32767
fmt.Println(math.MaxInt32)  // 2147483647
fmt.Println(math.MaxInt64)  // 9223372036854775807
fmt.Println(math.MinInt64)  // -9223372036854775808

fmt.Println(math.MaxFloat32) // 3.4028234663852886e+38

Special Values: Inf and NaN #

math supports the IEEE 754 special values that you need to understand when working with float64:

// Infinity — the result of operations exceeding the float64 range
posInf := math.Inf(1)   // +∞
negInf := math.Inf(-1)  // -∞

fmt.Println(math.IsInf(posInf, 1))  // true
fmt.Println(math.IsInf(negInf, -1)) // true
fmt.Println(1.0 / 0.0)              // compile error — Go doesn't allow this
fmt.Println(math.Log(0))            // -Inf

// NaN — Not a Number, the result of undefined operations
nan := math.NaN()
fmt.Println(math.IsNaN(nan))        // true
fmt.Println(nan == nan)             // false! NaN is not equal to itself
fmt.Println(math.Sqrt(-1))          // NaN

// ANTI-PATTERN: comparing float64 with ==
var x float64 = math.Sqrt(-1)
if x == math.NaN() {      // always false, even if x is NaN
    fmt.Println("this is NaN")
}

// CORRECT: use math.IsNaN
if math.IsNaN(x) {
    fmt.Println("this is NaN")
}

Rounding: Floor, Ceil, Round, and Trunc #

These four rounding functions have different behaviors and are often confusing if not understood well.

FunctionBehaviorExample (+2.7)Example (-2.7)
math.Floor(x)Round down (floor)2-3
math.Ceil(x)Round up (ceiling)3-2
math.Round(x)Round to nearest (half away from zero)3-3
math.Trunc(x)Truncate decimals (toward zero)2-2
x := 2.7
y := -2.7

fmt.Println(math.Floor(x), math.Floor(y))   // 2  -3
fmt.Println(math.Ceil(x), math.Ceil(y))     // 3  -2
fmt.Println(math.Round(x), math.Round(y))   // 3  -3
fmt.Println(math.Trunc(x), math.Trunc(y))   // 2  -2

// Mod — the remainder (modulo) for float64
fmt.Println(math.Mod(10.5, 3.0)) // 1.5
fmt.Println(math.Mod(-10.5, 3.0)) // -1.5

// Modf — split the integer and fractional parts
integer, fractional := math.Modf(3.75)
fmt.Println(integer, fractional) // 3  0.75

integer, fractional = math.Modf(-3.75)
fmt.Println(integer, fractional) // -3  -0.75

Rounding to N Decimal Places #

math doesn’t provide a function to round to N decimal places directly, but this pattern is very common in applications:

// Round to 2 decimal places
func roundTo(x float64, decimals int) float64 {
    factor := math.Pow(10, float64(decimals))
    return math.Round(x*factor) / factor
}

fmt.Println(roundTo(3.14159, 2)) // 3.14
fmt.Println(roundTo(2.675, 2))   // 2.68
fmt.Println(roundTo(1.005, 2))   // might not be 1.01 because of floating point!
Money rounding must not use float64. The binary representation of float64 can’t represent all decimals exactly — for example 0.1 + 0.2 produces 0.30000000000000004, not 0.3. For financial calculations, use integers (cents/smallest unit) or the math/big package with big.Rat / big.Float, which offer exact precision.

Roots and Powers #

Sqrt, Cbrt, and Pow #

// Square root
fmt.Println(math.Sqrt(16))   // 4
fmt.Println(math.Sqrt(2))    // 1.4142135623730951
fmt.Println(math.Sqrt(-1))   // NaN — the root of a negative is not real

// Cube root
fmt.Println(math.Cbrt(27))   // 3
fmt.Println(math.Cbrt(-8))   // -2 (unlike Sqrt, Cbrt supports negatives)

// Power — Pow(x, y) = x^y
fmt.Println(math.Pow(2, 10))  // 1024
fmt.Println(math.Pow(3, 3))   // 27
fmt.Println(math.Pow(4, 0.5)) // 2 (same as Sqrt(4))
fmt.Println(math.Pow(2, -1))  // 0.5

// Pow10 — powers of 10, more efficient than Pow(10, n)
fmt.Println(math.Pow10(3))  // 1000
fmt.Println(math.Pow10(-2)) // 0.01

Hypot — The Hypotenuse Length #

math.Hypot(p, q) computes √(p² + q²) with better numerical accuracy than a manual implementation:

// ANTI-PATTERN: compute manually — prone to overflow for large values
func distanceManual(x, y float64) float64 {
    return math.Sqrt(x*x + y*y) // can overflow if x or y is very large
}

// CORRECT: use Hypot — handles edge cases internally
fmt.Println(math.Hypot(3, 4))   // 5
fmt.Println(math.Hypot(5, 12))  // 13

// Distance between two coordinate points
func distance(x1, y1, x2, y2 float64) float64 {
    return math.Hypot(x2-x1, y2-y1)
}

Logarithms and Exponents #

Log, Log2, Log10 #

// Log — natural logarithm (base e)
fmt.Println(math.Log(math.E))   // 1
fmt.Println(math.Log(1))        // 0
fmt.Println(math.Log(0))        // -Inf
fmt.Println(math.Log(-1))       // NaN

// Log2 — base-2 logarithm
fmt.Println(math.Log2(1024))    // 10
fmt.Println(math.Log2(8))       // 3

// Log10 — base-10 logarithm
fmt.Println(math.Log10(1000))   // 3
fmt.Println(math.Log10(0.01))   // -2

// Logarithm to any base N — the change of base formula
func logN(x, base float64) float64 {
    return math.Log(x) / math.Log(base)
}
fmt.Println(logN(81, 3)) // 4 (3^4 = 81)

Exp and Exp2 #

// Exp — e^x (the inverse of Log)
fmt.Println(math.Exp(1))    // 2.718281828459045 (= e)
fmt.Println(math.Exp(0))    // 1
fmt.Println(math.Exp(3))    // 20.085536923187668

// Exp2 — 2^x (the inverse of Log2)
fmt.Println(math.Exp2(10))  // 1024
fmt.Println(math.Exp2(0.5)) // 1.4142135623730951 (= √2)

// Expm1 — e^x - 1, accurate for x near zero
// Use this instead of Exp(x)-1 for very small x
fmt.Println(math.Expm1(0.0001))         // 0.00010000500016667084
fmt.Println(math.Exp(0.0001) - 1)       // 0.00010000500016667084 (same)
fmt.Println(math.Expm1(1e-20))          // 1e-20 (accurate)
fmt.Println(math.Exp(1e-20) - 1)        // 0 (precision lost!)

Trigonometry #

All trigonometric functions in math use radians, not degrees. Converting from degrees to radians uses the formula degrees × π / 180.

// Degrees <-> radians conversion
func toRadians(degrees float64) float64 {
    return degrees * math.Pi / 180
}

func toDegrees(radians float64) float64 {
    return radians * 180 / math.Pi
}

// Basic trigonometric functions
fmt.Println(math.Sin(math.Pi / 2))    // 1 (sin 90°)
fmt.Println(math.Cos(0))              // 1 (cos 0°)
fmt.Println(math.Tan(math.Pi / 4))    // 0.9999999999999999 ≈ 1 (tan 45°)

// Sin and Cos together (more efficient than calling both)
s, c := math.Sincos(math.Pi / 4)
fmt.Printf("sin(45°)=%.4f, cos(45°)=%.4f\n", s, c) // 0.7071, 0.7071

// Inverse functions (arc)
fmt.Println(math.Asin(1))             // 1.5707963267948966 (= π/2)
fmt.Println(math.Acos(1))             // 0
fmt.Println(math.Atan(1))             // 0.7853981633974483 (= π/4)

// Atan2 — the angle from coordinates (x, y), handling all quadrants
fmt.Println(math.Atan2(1, 1))         // π/4 (quadrant I)
fmt.Println(math.Atan2(1, -1))        // 3π/4 (quadrant II)
fmt.Println(math.Atan2(-1, -1))       // -3π/4 (quadrant III)

Pattern: Coordinate Conversion #

// Convert Cartesian coordinates to polar
func toPolar(x, y float64) (r, theta float64) {
    r = math.Hypot(x, y)
    theta = math.Atan2(y, x) // the angle in radians
    return
}

// Convert polar coordinates to Cartesian
func toCartesian(r, theta float64) (x, y float64) {
    x = r * math.Cos(theta)
    y = r * math.Sin(theta)
    return
}

r, theta := toPolar(3, 4)
fmt.Printf("r=%.2f, theta=%.4f rad (%.2f°)\n",
    r, theta, toDegrees(theta)) // r=5.00, theta=0.9273 rad (53.13°)

Absolute Values, Min, and Max #

Abs, Min, Max, and Dim #

// Abs — the absolute value
fmt.Println(math.Abs(-5.5))   // 5.5
fmt.Println(math.Abs(3.2))    // 3.2
fmt.Println(math.Abs(0))      // 0

// Min and Max — the smallest/largest of two float64s
fmt.Println(math.Min(3.5, 7.2))   // 3.5
fmt.Println(math.Max(3.5, 7.2))   // 7.2
fmt.Println(math.Min(math.NaN(), 5)) // NaN — note this behavior

// Dim — max(x-y, 0) — useful for calculations that must not be negative
fmt.Println(math.Dim(5, 3))   // 2  (5-3=2)
fmt.Println(math.Dim(3, 5))   // 0  (3-5=-2, returned as 0)
fmt.Println(math.Dim(5, 5))   // 0

// Pattern: calculate remaining time (must not be negative)
func timeRemaining(deadline, now float64) float64 {
    return math.Dim(deadline, now)
}
math.Min and math.Max only work with float64. For integers (int, int64, etc.), Go 1.21 added min() and max() as built-in functions that can be used directly without any import. For Go versions before 1.21, you need to write manual comparisons using if.

Signbit and Copysign #

// Signbit — is the value negative (including -0 and -Inf)
fmt.Println(math.Signbit(-3.14))      // true
fmt.Println(math.Signbit(3.14))       // false
fmt.Println(math.Signbit(math.Inf(-1))) // true

// Copysign — copy the sign from y to x
fmt.Println(math.Copysign(5, -1))     // -5
fmt.Println(math.Copysign(5, 1))      // 5
fmt.Println(math.Copysign(-5, 1))     // 5

The math/rand Package — Random Numbers #

The math/rand package provides a fast pseudo-random number generator, suitable for simulation, testing, games, and data shuffling. This isn’t cryptographically secure random — for security, use crypto/rand.

Basic Usage (Go 1.20+) #

Since Go 1.20, math/rand automatically uses a random seed, so you no longer need to call rand.Seed() manually. The top-level functions can be used directly:

import (
    "fmt"
    "math/rand"
)

// Random integer in [0, n)
fmt.Println(rand.Intn(100))     // a random number 0-99
fmt.Println(rand.Intn(6) + 1)   // a dice simulation: 1-6

// Random float in [0.0, 1.0)
fmt.Println(rand.Float64())     // e.g.: 0.6046602879796196
fmt.Println(rand.Float32())

// Float in the range [min, max)
func randomRange(min, max float64) float64 {
    return min + rand.Float64()*(max-min)
}
fmt.Printf("%.2f\n", randomRange(1.5, 3.5)) // e.g.: 2.37

rand.New and rand.Source — Full Control #

For needs requiring reproducibility (for example testing or simulations that must be repeatable), create a rand.Rand instance with a known seed:

// Source with a fixed seed — produces the same sequence every time
src := rand.NewSource(42)
r := rand.New(src)

fmt.Println(r.Intn(100)) // always the same if the seed is the same
fmt.Println(r.Intn(100))
fmt.Println(r.Intn(100))

// This instance is not thread-safe — create one per goroutine
// or use a sync.Mutex for concurrent access

Shuffle — Randomizing Slice Order #

// Randomize a slice's order
fruits := []string{"apple", "orange", "mango", "banana", "durian"}
rand.Shuffle(len(fruits), func(i, j int) {
    fruits[i], fruits[j] = fruits[j], fruits[i]
})
fmt.Println(fruits) // random order

// Take N random elements from a slice (sampling without replacement)
func takeRandom(slice []string, n int) []string {
    copy := make([]string, len(slice))
    copy(copy, slice)
    rand.Shuffle(len(copy), func(i, j int) {
        copy[i], copy[j] = copy[j], copy[i]
    })
    return copy[:n]
}

sample := takeRandom(fruits, 3)
fmt.Println(sample) // 3 random fruits

Statistical Distributions #

// NormFloat64 — the standard normal distribution (mean=0, stddev=1)
value := rand.NormFloat64()

// Convert to a specific mean and stddev: X = mean + stddev * NormFloat64()
mean := 170.0   // average height (cm)
stddev := 7.0
height := mean + stddev*rand.NormFloat64()
fmt.Printf("Simulated height: %.1f cm\n", height)

// ExpFloat64 — the exponential distribution (rate=1)
// Useful for simulating inter-arrival times (queuing theory)
waitTime := rand.ExpFloat64()
fmt.Printf("Simulated wait time: %.3f\n", waitTime)

Security: math/rand vs crypto/rand #

flowchart TD
    A{"What is this\nrandom number for?"} --> B{"Cryptographic\nsecurity?"}
    B -- Yes --> C["crypto/rand"]
    B -- No --> D{"Reproducible\nfor testing?"}
    D -- Yes --> E["rand.New with\na fixed seed"]
    D -- No --> F["rand.Intn / rand.Float64\ndirectly — Go 1.20+"]

    C --> G["Tokens, passwords,\nencryption keys,\nCSRF tokens"]
    E --> H["Simulation, unit tests,\ndummy data"]
    F --> I["Games, shuffle,\nsampling, UI"]
// math/rand — DON'T use for security
token := fmt.Sprintf("%d", rand.Int63()) // ✗ predictable

// crypto/rand — for security tokens
import cryptorand "crypto/rand"
import "encoding/hex"

b := make([]byte, 16)
cryptorand.Read(b)
token := hex.EncodeToString(b) // ✓ cryptographically secure

The math/big Package — Arbitrary Precision #

Go’s built-in numeric types have limits: int64 maxes out around 9.2 × 10¹⁸ and float64 loses precision for certain decimals. The math/big package provides three types to go beyond these limits.

TypeUse
big.IntArbitrary-precision integers — large factorials, cryptography
big.FloatArbitrary-precision floats — scientific computation, financial calculations
big.RatExact rational numbers (p/q) — avoid floating point errors entirely

big.Int — Unlimited Integers #

import "math/big"

// Factorial of 100 — far beyond int64
func factorial(n int64) *big.Int {
    result := big.NewInt(1)
    for i := int64(2); i <= n; i++ {
        result.Mul(result, big.NewInt(i))
    }
    return result
}

fmt.Println(factorial(20))  // 2432902008176640000
fmt.Println(factorial(100)) // 93326215443944152681699238856266700490715968264381621468592963895217...

// big.Int operations
a := big.NewInt(1000000000000) // 1 trillion
b := big.NewInt(999999999999)

sum := new(big.Int).Add(a, b)
prod := new(big.Int).Mul(a, b)
fmt.Println(sum)  // 1999999999999
fmt.Println(prod) // 999999999999000000000000

// Parsing from a string
c, ok := new(big.Int).SetString("12345678901234567890", 10)
if ok {
    fmt.Println(c)
}

// Comparison
cmp := a.Cmp(b) // -1 (a < b), 0 (a == b), 1 (a > b)
fmt.Println(cmp) // 1 (a > b)

big.Float — High-Precision Floats #

// Calculate π with 200-bit precision
func calculatePi() *big.Float {
    // A simple implementation with the Leibniz series (illustration only)
    prec := uint(200)
    pi := new(big.Float).SetPrec(prec)
    // ... the actual implementation using a more efficient algorithm
    return pi
}

// Basic big.Float usage
a := new(big.Float).SetPrec(256).SetFloat64(1.0)
b := new(big.Float).SetPrec(256).SetFloat64(3.0)

result := new(big.Float).Quo(a, b) // 1/3 with high precision
fmt.Println(result.Text('f', 50))  // 0.33333333333333333333333333333333333333333333333333

// Compare with a regular float64
fmt.Println(1.0 / 3.0) // 0.3333333333333333 (only 16 digits)

big.Rat — Exact Rational Numbers #

big.Rat represents numbers as a fraction p/q without losing any precision. This is the best solution for financial or scientific calculations needing exact precision.

// big.Rat — no floating point errors
a := big.NewRat(1, 10)  // 1/10 = 0.1
b := big.NewRat(2, 10)  // 2/10 = 0.2

sum := new(big.Rat).Add(a, b)
fmt.Println(sum)                    // 3/10
fmt.Println(sum.FloatString(1))     // 0.3 (exact!)

// Compare with float64
fmt.Println(0.1 + 0.2)             // 0.30000000000000004 (not exact)
fmt.Println(0.1 + 0.2 == 0.3)      // false

// big.Rat for price calculations
price := big.NewRat(9999, 100)     // Rp 99.99
tax := big.NewRat(11, 100)         // 11%

taxValue := new(big.Rat).Mul(price, tax)
total := new(big.Rat).Add(price, taxValue)
fmt.Println(total.FloatString(2))  // "110.99" — exact

Safe Float Comparison #

Comparing float64 with == often produces unexpected results because the binary representation isn’t always exact. Use epsilon comparison to compare float values.

// ANTI-PATTERN: compare floats with == directly
a := 0.1 + 0.2
b := 0.3
if a == b { // false! even though mathematically equal
    fmt.Println("equal")
}

// CORRECT: use an epsilon tolerance
const epsilon = 1e-9

func almostEqual(a, b float64) bool {
    return math.Abs(a-b) < epsilon
}

fmt.Println(almostEqual(0.1+0.2, 0.3)) // true

// For relative comparison (more robust for large/small numbers)
func almostEqualRelative(a, b, tolerance float64) bool {
    if a == b {
        return true
    }
    diff := math.Abs(a - b)
    norm := math.Max(math.Abs(a), math.Abs(b))
    return diff/norm < tolerance
}

fmt.Println(almostEqualRelative(1e10+0.001, 1e10, 1e-9)) // true
fmt.Println(almostEqualRelative(1.0, 2.0, 1e-9))          // false

Real-World Patterns #

Calculating the Haversine Distance (Earth Coordinates) #

The distance between two points on the Earth’s surface can’t be calculated with ordinary Pythagoras — it needs the Haversine formula, which accounts for the Earth’s curvature:

const earthRadius = 6371.0 // km

func haversineDistance(lat1, lon1, lat2, lon2 float64) float64 {
    // Convert degrees to radians
    dLat := toRadians(lat2 - lat1)
    dLon := toRadians(lon2 - lon1)
    lat1 = toRadians(lat1)
    lat2 = toRadians(lat2)

    a := math.Sin(dLat/2)*math.Sin(dLat/2) +
        math.Cos(lat1)*math.Cos(lat2)*
            math.Sin(dLon/2)*math.Sin(dLon/2)

    c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
    return earthRadius * c
}

func toRadians(degrees float64) float64 {
    return degrees * math.Pi / 180
}

// Jakarta to Surabaya
distance := haversineDistance(-6.2088, 106.8456, -7.2575, 112.7521)
fmt.Printf("Jakarta-Surabaya distance: %.0f km\n", distance) // ~664 km

Descriptive Statistics #

func statistics(data []float64) (mean, variance, stddev float64) {
    n := float64(len(data))
    if n == 0 {
        return
    }

    // Calculate the mean
    for _, v := range data {
        mean += v
    }
    mean /= n

    // Calculate the variance (Welford's method for numerical stability)
    for _, v := range data {
        diff := v - mean
        variance += diff * diff
    }
    variance /= n

    stddev = math.Sqrt(variance)
    return
}

data := []float64{2, 4, 4, 4, 5, 5, 7, 9}
mean, variance, stddev := statistics(data)
fmt.Printf("Mean: %.2f\n", mean)         // 5.00
fmt.Printf("Variance: %.2f\n", variance) // 4.00
fmt.Printf("Stddev: %.2f\n", stddev)     // 2.00

Data Normalization (Min-Max Scaling) #

func normalize(data []float64) []float64 {
    if len(data) == 0 {
        return nil
    }

    minVal := data[0]
    maxVal := data[0]
    for _, v := range data[1:] {
        minVal = math.Min(minVal, v)
        maxVal = math.Max(maxVal, v)
    }

    span := maxVal - minVal
    if span == 0 {
        return make([]float64, len(data)) // all zeros if everything is the same
    }

    result := make([]float64, len(data))
    for i, v := range data {
        result[i] = (v - minVal) / span
    }
    return result
}

data := []float64{10, 20, 30, 40, 50}
fmt.Println(normalize(data)) // [0 0.25 0.5 0.75 1]

A Simple Unique ID Generator #

import (
    cryptorand "crypto/rand"
    "encoding/binary"
    "fmt"
)

// A random 6-digit numeric ID (for OTP codes, PINs, etc.)
func generateOTP() string {
    var b [8]byte
    cryptorand.Read(b[:])
    n := binary.BigEndian.Uint64(b[:])
    otp := n % 1000000 // 6 digits
    return fmt.Sprintf("%06d", otp)
}

fmt.Println(generateOTP()) // "047291" (always 6 digits)

When to Switch to Alternatives #

Keep using math if:
  ✓ Common mathematical operations: roots, powers, trigonometry, logarithms
  ✓ Rounding and absolute values for float64
  ✓ Random numbers for simulation, games, testing, or data shuffling
  ✓ Mathematical constants (Pi, E, Phi, etc.)
  ✓ Checking NaN, Inf, and the boundary values of numeric types

Consider math/big if:
  ✗ Integers exceeding 9.2 × 10¹⁸ (the int64 limit)
  ✗ Financial calculations needing exact precision (use big.Rat)
  ✗ Cryptography requiring high-precision modular arithmetic
  ✗ Scientific computation needing more than 15-16 digits of precision

Consider crypto/rand if:
  ✗ Creating security tokens, session IDs, or encryption keys
  ✗ Any security-related random number needs

Consider external packages if:
  ✗ Linear algebra, matrices, FFT → gonum.org/v1/gonum
  ✗ Advanced statistics → gonum.org/v1/gonum/stat
  ✗ Symbolic computation or complex scientific calculations → the gonum ecosystem

Summary #

  • The math.Pi, math.E, math.Phi constants — already available with full float64 precision; no need to redefine them manually.
  • math.IsNaN and math.IsInf — always use these functions to check for NaN and Inf; comparing NaN == NaN is always false and will trap you.
  • math.Floor, math.Ceil, math.Round, math.Trunc — have different behaviors especially for negative numbers; understand the differences before using them.
  • Don’t use float64 for money — binary representation errors (0.1 + 0.2 ≠ 0.3) can cause financial discrepancies; use integers (cents) or big.Rat.
  • math.Hypot(p, q) — more accurate than math.Sqrt(p*p + q*q) because it avoids overflow for large values.
  • math/rand is auto-seeded since Go 1.20 — no more rand.Seed() needed; use rand.New(rand.NewSource(n)) only if you need reproducibility.
  • math/rand isn’t for security — use crypto/rand for tokens, passwords, encryption keys, and all cryptographic needs.
  • math/big provides big.Int (unlimited integers), big.Float (arbitrary precision), and big.Rat (exact rationals) — choose according to your precision needs.
  • Compare floats with an epsilon, not == — use math.Abs(a-b) < epsilon for comparisons robust against representation errors.

← Previous: IO   Next: Fmt →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact