Skip to main content
โšก Calmops

Math Operations and Random Numbers in Go

Math Operations and Random Numbers in Go

Go provides comprehensive support for mathematical operations through the math package and random number generation through the rand and crypto/rand packages. This guide covers everything you need for numerical computing in Go.

The Math Package

Basic Mathematical Functions

package main

import (
	"fmt"
	"math"
)

func main() {
	// Absolute value
	fmt.Println("Abs(-5):", math.Abs(-5))

	// Square root
	fmt.Println("Sqrt(16):", math.Sqrt(16))

	// Power
	fmt.Println("Pow(2, 8):", math.Pow(2, 8))

	// Ceiling and floor
	fmt.Println("Ceil(4.3):", math.Ceil(4.3))
	fmt.Println("Floor(4.7):", math.Floor(4.7))

	// Rounding
	fmt.Println("Round(4.5):", math.Round(4.5))
	fmt.Println("Trunc(4.9):", math.Trunc(4.9))

	// Minimum and maximum
	fmt.Println("Min(5, 3):", math.Min(5, 3))
	fmt.Println("Max(5, 3):", math.Max(5, 3))
}

Trigonometric Functions

package main

import (
	"fmt"
	"math"
)

func main() {
	// Sine, cosine, tangent (in radians)
	angle := math.Pi / 4 // 45 degrees

	fmt.Printf("Sin(ฯ€/4): %.4f\n", math.Sin(angle))
	fmt.Printf("Cos(ฯ€/4): %.4f\n", math.Cos(angle))
	fmt.Printf("Tan(ฯ€/4): %.4f\n", math.Tan(angle))

	// Inverse trigonometric functions
	fmt.Printf("Asin(0.707): %.4f\n", math.Asin(0.707))
	fmt.Printf("Acos(0.707): %.4f\n", math.Acos(0.707))
	fmt.Printf("Atan(1): %.4f\n", math.Atan(1))

	// Atan2 for angle calculation
	fmt.Printf("Atan2(1, 1): %.4f\n", math.Atan2(1, 1))

	// Convert degrees to radians
	degrees := 45.0
	radians := degrees * math.Pi / 180
	fmt.Printf("%f degrees = %f radians\n", degrees, radians)
}

Logarithmic and Exponential Functions

package main

import (
	"fmt"
	"math"
)

func main() {
	// Natural logarithm
	fmt.Printf("Log(2.718): %.4f\n", math.Log(math.E))

	// Base 10 logarithm
	fmt.Printf("Log10(100): %.4f\n", math.Log10(100))

	// Base 2 logarithm
	fmt.Printf("Log2(8): %.4f\n", math.Log2(8))

	// Exponential (e^x)
	fmt.Printf("Exp(1): %.4f\n", math.Exp(1))

	// Power with base e
	fmt.Printf("Exp2(3): %.4f\n", math.Exp2(3))

	// Hyperbolic functions
	fmt.Printf("Sinh(1): %.4f\n", math.Sinh(1))
	fmt.Printf("Cosh(1): %.4f\n", math.Cosh(1))
	fmt.Printf("Tanh(1): %.4f\n", math.Tanh(1))
}

Special Values and Constants

package main

import (
	"fmt"
	"math"
)

func main() {
	// Mathematical constants
	fmt.Println("Pi:", math.Pi)
	fmt.Println("E:", math.E)
	fmt.Println("Phi (Golden Ratio):", math.Phi)
	fmt.Println("Sqrt2:", math.Sqrt2)
	fmt.Println("SqrtE:", math.SqrtE)
	fmt.Println("SqrtPi:", math.SqrtPi)
	fmt.Println("SqrtPhi:", math.SqrtPhi)

	// Special floating point values
	fmt.Println("Inf:", math.Inf(1))
	fmt.Println("-Inf:", math.Inf(-1))
	fmt.Println("NaN:", math.NaN())

	// Check for special values
	fmt.Println("IsInf(Inf(1)):", math.IsInf(math.Inf(1), 1))
	fmt.Println("IsNaN(NaN()):", math.IsNaN(math.NaN()))
	fmt.Println("IsFinite(5.0):", math.IsFinite(5.0))
}

Random Number Generation

Using the rand Package

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	// Seed the random number generator
	rand.Seed(time.Now().UnixNano())

	// Generate random integers
	fmt.Println("Random int:", rand.Int())
	fmt.Println("Random int63:", rand.Int63())

	// Generate random integers in range [0, n)
	fmt.Println("Random int in [0, 100):", rand.Intn(100))

	// Generate random float64 in [0.0, 1.0)
	fmt.Println("Random float64:", rand.Float64())

	// Generate random float64 in [0.0, n)
	fmt.Println("Random float64 in [0, 100):", rand.Float64()*100)
}

Seeding for Reproducibility

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	// Seed with fixed value for reproducible results
	rand.Seed(42)

	fmt.Println("First run:")
	for i := 0; i < 3; i++ {
		fmt.Println(rand.Intn(100))
	}

	// Reseed with same value
	rand.Seed(42)

	fmt.Println("\nSecond run (same seed):")
	for i := 0; i < 3; i++ {
		fmt.Println(rand.Intn(100))
	}
}

Random Selections

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	// Shuffle a slice
	numbers := []int{1, 2, 3, 4, 5}
	rand.Shuffle(len(numbers), func(i, j int) {
		numbers[i], numbers[j] = numbers[j], numbers[i]
	})
	fmt.Println("Shuffled:", numbers)

	// Random selection from slice
	choices := []string{"apple", "banana", "cherry", "date"}
	fmt.Println("Random choice:", choices[rand.Intn(len(choices))])

	// Generate random permutation
	perm := rand.Perm(5)
	fmt.Println("Random permutation:", perm)
}

Cryptographically Secure Random Numbers

package main

import (
	"crypto/rand"
	"fmt"
	"log"
	"math/big"
)

func main() {
	// Generate cryptographically secure random bytes
	bytes := make([]byte, 16)
	_, err := rand.Read(bytes)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Random bytes: %x\n", bytes)

	// Generate random big integer
	max := big.NewInt(100)
	randomBig, err := rand.Int(rand.Reader, max)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Random big int:", randomBig)

	// Generate random number in range
	randomInRange, err := rand.Int(rand.Reader, big.NewInt(100))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Random in [0, 100):", randomInRange)
}

Practical Examples

Simulating Dice Rolls

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	// Roll a die 10 times
	fmt.Println("Rolling a die 10 times:")
	for i := 0; i < 10; i++ {
		roll := rand.Intn(6) + 1 // 1-6
		fmt.Printf("Roll %d: %d\n", i+1, roll)
	}

	// Simulate multiple dice rolls
	fmt.Println("\nRolling two dice 5 times:")
	for i := 0; i < 5; i++ {
		die1 := rand.Intn(6) + 1
		die2 := rand.Intn(6) + 1
		fmt.Printf("Roll %d: %d + %d = %d\n", i+1, die1, die2, die1+die2)
	}
}

Monte Carlo Simulation

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	// Estimate Pi using Monte Carlo method
	numSamples := 1000000
	pointsInCircle := 0

	for i := 0; i < numSamples; i++ {
		x := rand.Float64()
		y := rand.Float64()
		distance := math.Sqrt(x*x + y*y)

		if distance <= 1.0 {
			pointsInCircle++
		}
	}

	// Pi โ‰ˆ 4 * (points in circle / total points)
	estimatedPi := 4.0 * float64(pointsInCircle) / float64(numSamples)
	fmt.Printf("Estimated Pi: %.6f\n", estimatedPi)
	fmt.Printf("Actual Pi: %.6f\n", math.Pi)
	fmt.Printf("Error: %.6f\n", math.Abs(estimatedPi-math.Pi))
}

Random String Generation

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	// Generate random string
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	length := 10

	randomString := make([]byte, length)
	for i := range randomString {
		randomString[i] = charset[rand.Intn(len(charset))]
	}

	fmt.Println("Random string:", string(randomString))

	// Generate multiple random strings
	fmt.Println("\nRandom strings:")
	for i := 0; i < 5; i++ {
		str := make([]byte, 8)
		for j := range str {
			str[j] = charset[rand.Intn(len(charset))]
		}
		fmt.Println(string(str))
	}
}

Weighted Random Selection

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	// Weighted selection
	type Option struct {
		name   string
		weight int
	}

	options := []Option{
		{"common", 70},
		{"uncommon", 25},
		{"rare", 4},
		{"legendary", 1},
	}

	// Calculate total weight
	totalWeight := 0
	for _, opt := range options {
		totalWeight += opt.weight
	}

	// Simulate 1000 selections
	counts := make(map[string]int)
	for i := 0; i < 1000; i++ {
		r := rand.Intn(totalWeight)
		cumulative := 0

		for _, opt := range options {
			cumulative += opt.weight
			if r < cumulative {
				counts[opt.name]++
				break
			}
		}
	}

	fmt.Println("Distribution from 1000 selections:")
	for _, opt := range options {
		fmt.Printf("%s: %d (%.1f%%)\n", opt.name, counts[opt.name], float64(counts[opt.name])/10)
	}
}

Best Practices

โœ… Good Practices

// Use crypto/rand for security-sensitive operations
func generateSecureToken() ([]byte, error) {
	token := make([]byte, 32)
	_, err := rand.Read(token)
	return token, err
}

// Seed once at program start
func init() {
	rand.Seed(time.Now().UnixNano())
}

// Use math constants instead of hardcoding
func calculateCircleArea(radius float64) float64 {
	return math.Pi * radius * radius
}

// Handle special floating point values
func safeLog(x float64) float64 {
	if x <= 0 {
		return math.NaN()
	}
	return math.Log(x)
}

โŒ Anti-Patterns

// Don't seed multiple times
func badRandom() {
	rand.Seed(time.Now().UnixNano())
	rand.Seed(time.Now().UnixNano())
	// Reduces randomness
}

// Don't use math/rand for security
func badToken() {
	token := rand.Int63()
	// Not cryptographically secure
}

// Don't ignore special values
func badCalculation(x float64) float64 {
	return math.Log(x) // Panics if x <= 0
}

// Don't hardcode mathematical constants
func badArea(r float64) float64 {
	return 3.14159 * r * r // Less precise than math.Pi
}

Common Pitfalls

Seeding Issues

// โŒ Wrong: Seeding in loop reduces randomness
for i := 0; i < 10; i++ {
	rand.Seed(time.Now().UnixNano())
	fmt.Println(rand.Intn(100))
}

// โœ… Correct: Seed once at startup
func init() {
	rand.Seed(time.Now().UnixNano())
}

Floating Point Precision

// โŒ Wrong: Direct comparison of floats
if math.Sqrt(2)*math.Sqrt(2) == 2 {
	fmt.Println("Equal")
}

// โœ… Correct: Use epsilon for comparison
epsilon := 1e-9
if math.Abs(math.Sqrt(2)*math.Sqrt(2)-2) < epsilon {
	fmt.Println("Equal")
}

Range Errors

// โŒ Wrong: Incorrect range calculation
randomInRange := rand.Intn(100) // [0, 100)

// โœ… Correct: Adjust for desired range
randomInRange := rand.Intn(100) + 1 // [1, 100]

Resources

Summary

Go’s math and random packages provide powerful tools for numerical computing:

  • Use math package for mathematical functions and constants
  • Use math/rand for general-purpose random numbers
  • Use crypto/rand for security-sensitive operations
  • Seed once at program startup
  • Handle special floating point values properly
  • Use epsilon for floating point comparisons

With these tools, you can implement sophisticated numerical algorithms and simulations in Go.

Comments