Why This Matters
Think of building a financial trading system that processes millions of transactions per minute, or a scientific simulation that models complex physical phenomena, or a machine learning pipeline that processes terabytes of data. These applications require precise mathematical calculations, statistical analysis, and optimized numerical algorithms.
Math and science libraries are the computational foundation that separates simple applications from powerful data-driven systems. They enable:
- Financial Systems: Real-time risk calculations, option pricing, and portfolio optimization
- Scientific Computing: Weather modeling, molecular dynamics, and quantum simulations
- Data Analytics: Statistical analysis, machine learning algorithms, and predictive modeling
- Engineering: Signal processing, control systems, and optimization problems
- Game Development: Physics engines, graphics rendering, and procedural generation
Learning Objectives
After completing this article, you will be able to:
- Use Go's Math Package: Leverage mathematical functions for complex calculations
- Implement Statistics: Calculate statistical measures and perform data analysis
- Handle Precision: Work with floating-point arithmetic and precision challenges
- Optimize Performance: Write efficient numerical algorithms
- Apply Scientific Patterns: Use mathematical models and simulations
- Validate Results: Test and verify mathematical computations
- Integrate Libraries: Use external math and science packages effectively
Core Concepts
Mathematical Computing in Go
Go provides a robust foundation for mathematical computing through several key packages:
math: Core mathematical functions, constants, and operationsmath/big: Arbitrary-precision arithmetic for large numbersmath/cmplx: Complex number operations and functionsmath/rand: Random number generation- Third-party libraries: Gonum for scientific computing, statistics, and plotting
These packages work together to provide a complete mathematical computing ecosystem, from basic arithmetic to complex scientific simulations.
Precision and Performance Considerations
Mathematical computing presents unique challenges:
- Floating-Point Precision: Understanding IEEE 754 standards and numerical stability
- Performance Optimization: Vectorization, parallelization, and memory efficiency
- Numerical Stability: Avoiding overflow, underflow, and accumulation errors
- Algorithm Selection: Choosing the right algorithm for specific problems
Practical Examples
Mathematical Functions and Constants
Go's math package provides comprehensive mathematical operations and constants.
1package main
2
3import (
4 "fmt"
5 "math"
6)
7
8// run
9func main() {
10 fmt.Println("=== Mathematical Functions and Constants ===")
11
12 // 1. Basic mathematical constants
13 fmt.Println("\n1. Mathematical Constants:")
14 fmt.Printf("π: %.15f\n", math.Pi)
15 fmt.Printf("e: %.15f\n", math.E)
16 fmt.Printf("Golden ratio: %.15f\n", math.Phi)
17 fmt.Printf("Square root of 2: %.15f\n", math.Sqrt2)
18 fmt.Printf("Natural log of 2: %.15f\n", math.Ln2)
19
20 // 2. Basic operations
21 fmt.Println("\n2. Basic Operations:")
22 x := 2.7
23 y := 1.3
24
25 fmt.Printf("Absolute value of %.2f: %.2f\n", -x, math.Abs(-x))
26 fmt.Printf("Power: %.2f^%.2f = %.4f\n", x, y, math.Pow(x, y))
27 fmt.Printf("Square root: sqrt(%.2f) = %.4f\n", x, math.Sqrt(x))
28 fmt.Printf("Cube root: cbrt(%.2f) = %.4f\n", x, math.Cbrt(x))
29
30 // 3. Trigonometric functions
31 fmt.Println("\n3. Trigonometric Functions:")
32 angle := math.Pi / 4 // 45 degrees
33
34 fmt.Printf("Angle: %.4f radians\n", angle, angle*180/math.Pi)
35 fmt.Printf("sin(%.4f): %.4f\n", angle, math.Sin(angle))
36 fmt.Printf("cos(%.4f): %.4f\n", angle, math.Cos(angle))
37 fmt.Printf("tan(%.4f): %.4f\n", angle, math.Tan(angle))
38 fmt.Printf("arcsin(%.4f): %.4f radians\n", math.Sin(angle), math.Asin(math.Sin(angle)))
39
40 // 4. Hyperbolic functions
41 fmt.Println("\n4. Hyperbolic Functions:")
42 value := 1.0
43
44 fmt.Printf("sinh(%.1f): %.4f\n", value, math.Sinh(value))
45 fmt.Printf("cosh(%.1f): %.4f\n", value, math.Cosh(value))
46 fmt.Printf("tanh(%.1f): %.4f\n", value, math.Tanh(value))
47
48 // 5. Logarithmic and exponential functions
49 fmt.Println("\n5. Logarithmic and Exponential Functions:")
50 base := 2.0
51 exp := 8.0
52
53 fmt.Printf("exp(%.1f): %.4f\n", 1.0, math.Exp(1.0))
54 fmt.Printf("exp2(%.1f): %.4f\n", base, math.Exp2(base))
55 fmt.Printf("log(%.1f): %.4f\n", exp, math.Log(exp))
56 fmt.Printf("log10(%.1f): %.4f\n", exp, math.Log10(exp))
57 fmt.Printf("log2(%.1f): %.4f\n", exp, math.Log2(exp))
58
59 // 6. Rounding functions
60 fmt.Println("\n6. Rounding Functions:")
61 numbers := []float64{3.14159, -2.71828, 4.5, -3.5}
62
63 for _, num := range numbers {
64 fmt.Printf("%.5f -> ceil: %.1f, floor: %.1f, round: %.1f\n",
65 num, math.Ceil(num), math.Floor(num), math.Round(num))
66 }
67
68 // 7. Special functions
69 fmt.Println("\n7. Special Functions:")
70 x = 1.5
71 fmt.Printf("Gamma(%.1f): %.4f\n", x, math.Gamma(x))
72 fmt.Printf("LogGamma(%.1f): %.4f\n", x, math.LogGamma(x))
73 fmt.Printf("Erf(%.1f): %.4f\n", x, math.Erf(x))
74 fmt.Printf("Erfc(%.1f): %.4f\n", x, math.Erfc(x))
75}
Real-World Applications:
- Engineering: Signal processing, control systems, filter design
- Physics: Wave functions, quantum mechanics, thermodynamics
- Graphics: 3D transformations, lighting calculations, animation curves
- Finance: Option pricing, risk calculations, portfolio optimization
💡 Performance Tip: Use math.Float64bits() and math.Float64frombits() for bitwise floating-point operations when optimizing performance-critical code.
Statistical Analysis
Statistical computing is essential for data analysis, machine learning, and scientific research.
1package main
2
3import (
4 "fmt"
5 "math"
6 "sort"
7)
8
9// run
10func main() {
11 fmt.Println("=== Statistical Analysis ===")
12
13 // Sample data set
14 data := []float64{2.3, 4.5, 1.8, 3.7, 5.2, 2.9, 4.1, 3.3, 2.1, 4.8}
15
16 // 1. Basic descriptive statistics
17 fmt.Println("\n1. Descriptive Statistics:")
18 mean, median, mode := calculateBasicStats(data)
19 fmt.Printf("Mean: %.4f\n", mean)
20 fmt.Printf("Median: %.4f\n", median)
21 fmt.Printf("Mode: %.4f\n", mode)
22
23 // 2. Measures of dispersion
24 fmt.Println("\n2. Measures of Dispersion:")
25 variance, stdDev, range_ := calculateDispersion(data)
26 fmt.Printf("Variance: %.4f\n", variance)
27 fmt.Printf("Standard Deviation: %.4f\n", stdDev)
28 fmt.Printf("Range: %.4f\n", range_)
29
30 // 3. Percentiles and quartiles
31 fmt.Println("\n3. Percentiles and Quartiles:")
32 percentiles := calculatePercentiles(data, []float64{25, 50, 75, 90, 95})
33 fmt.Printf("25th percentile: %.4f\n", percentiles[0])
34 fmt.Printf("50th percentile: %.4f\n", percentiles[1])
35 fmt.Printf("75th percentile: %.4f\n", percentiles[2])
36 fmt.Printf("90th percentile: %.4f\n", percentiles[3])
37 fmt.Printf("95th percentile: %.4f\n", percentiles[4])
38
39 // 4. Correlation analysis
40 fmt.Println("\n4. Correlation Analysis:")
41 x := []float64{1, 2, 3, 4, 5, 6, 7, 8}
42 y := []float64{2, 4, 5, 4, 5, 7, 8, 9}
43
44 correlation := calculateCorrelation(x, y)
45 fmt.Printf("Correlation coefficient: %.4f\n", correlation)
46 fmt.Printf("Interpretation: %s\n", interpretCorrelation(correlation))
47
48 // 5. Linear regression
49 fmt.Println("\n5. Linear Regression:")
50 slope, intercept, r2 := linearRegression(x, y)
51 fmt.Printf("Slope: %.4f\n", slope)
52 fmt.Printf("Intercept: %.4f\n", intercept)
53 fmt.Printf("R-squared: %.4f\n", r2)
54 fmt.Printf("Equation: y = %.4fx + %.4f\n", slope, intercept)
55
56 // 6. Outlier detection
57 fmt.Println("\n6. Outlier Detection:")
58 outliers := detectOutliers(data)
59 fmt.Printf("Outliers detected: %v\n", outliers)
60}
61
62func calculateBasicStats(data []float64) {
63 // Calculate mean
64 sum := 0.0
65 for _, value := range data {
66 sum += value
67 }
68 mean = sum / float64(len(data))
69
70 // Calculate median
71 sorted := make([]float64, len(data))
72 copy(sorted, data)
73 sort.Float64s(sorted)
74
75 n := len(sorted)
76 if n%2 == 0 {
77 median = / 2
78 } else {
79 median = sorted[n/2]
80 }
81
82 // Calculate mode
83 frequency := make(map[float64]int)
84 for _, value := range data {
85 frequency[value]++
86 }
87
88 maxFreq := 0
89 for value, freq := range frequency {
90 if freq > maxFreq {
91 maxFreq = freq
92 mode = value
93 }
94 }
95
96 return mean, median, mode
97}
98
99func calculateDispersion(data []float64) {
100 // Calculate mean
101 sum := 0.0
102 for _, value := range data {
103 sum += value
104 }
105 mean := sum / float64(len(data))
106
107 // Calculate variance
108 sumSquares := 0.0
109 for _, value := range data {
110 diff := value - mean
111 sumSquares += diff * diff
112 }
113 variance = sumSquares / float64(len(data))
114
115 // Standard deviation
116 stdDev = math.Sqrt(variance)
117
118 // Range
119 min := data[0]
120 max := data[0]
121 for _, value := range data {
122 if value < min {
123 min = value
124 }
125 if value > max {
126 max = value
127 }
128 }
129 range_ = max - min
130
131 return variance, stdDev, range_
132}
133
134func calculatePercentiles(data []float64, percentiles []float64) []float64 {
135 sorted := make([]float64, len(data))
136 copy(sorted, data)
137 sort.Float64s(sorted)
138
139 results := make([]float64, len(percentiles))
140 n := len(sorted)
141
142 for i, p := range percentiles {
143 index := * float64(n-1)
144 lower := int(math.Floor(index))
145 upper := int(math.Ceil(index))
146
147 if lower == upper {
148 results[i] = sorted[lower]
149 } else {
150 weight := index - float64(lower)
151 results[i] = sorted[lower]*(1-weight) + sorted[upper]*weight
152 }
153 }
154
155 return results
156}
157
158func calculateCorrelation(x, y []float64) float64 {
159 if len(x) != len(y) {
160 return 0.0
161 }
162
163 n := float64(len(x))
164
165 // Calculate means
166 sumX, sumY := 0.0, 0.0
167 for i := range x {
168 sumX += x[i]
169 sumY += y[i]
170 }
171 meanX, meanY := sumX/n, sumY/n
172
173 // Calculate correlation
174 sumXY, sumX2, sumY2 := 0.0, 0.0, 0.0
175 for i := range x {
176 dx := x[i] - meanX
177 dy := y[i] - meanY
178 sumXY += dx * dy
179 sumX2 += dx * dx
180 sumY2 += dy * dy
181 }
182
183 if sumX2 == 0 || sumY2 == 0 {
184 return 0.0
185 }
186
187 return sumXY / math.Sqrt(sumX2*sumY2)
188}
189
190func interpretCorrelation(r float64) string {
191 abs := math.Abs(r)
192 switch {
193 case abs >= 0.9:
194 return "Very strong correlation"
195 case abs >= 0.7:
196 return "Strong correlation"
197 case abs >= 0.5:
198 return "Moderate correlation"
199 case abs >= 0.3:
200 return "Weak correlation"
201 default:
202 return "Very weak or no correlation"
203 }
204}
205
206func linearRegression(x, y []float64) {
207 n := float64(len(x))
208
209 sumX, sumY := 0.0, 0.0
210 sumXY, sumX2, sumY2 := 0.0, 0.0, 0.0
211
212 for i := range x {
213 sumX += x[i]
214 sumY += y[i]
215 sumXY += x[i] * y[i]
216 sumX2 += x[i] * x[i]
217 sumY2 += y[i] * y[i]
218 }
219
220 // Calculate slope and intercept
221 denominator := n*sumX2 - sumX*sumX
222 if denominator == 0 {
223 return 0, 0, 0
224 }
225
226 slope = / denominator
227 intercept = / n
228
229 // Calculate R-squared
230 meanY := sumY / n
231 ssTotal, ssResidual := 0.0, 0.0
232
233 for i := range x {
234 yPredicted := slope*x[i] + intercept
235 ssTotal += *
236 ssResidual += *
237 }
238
239 if ssTotal == 0 {
240 r2 = 0
241 } else {
242 r2 = 1 - ssResidual/ssTotal
243 }
244
245 return slope, intercept, r2
246}
247
248func detectOutliers(data []float64) []float64 {
249 // Use IQR method
250 sorted := make([]float64, len(data))
251 copy(sorted, data)
252 sort.Float64s(sorted)
253
254 n := len(sorted)
255 q1 := sorted[n/4]
256 q3 := sorted[3*n/4]
257 iqr := q3 - q1
258
259 lowerBound := q1 - 1.5*iqr
260 upperBound := q3 + 1.5*iqr
261
262 var outliers []float64
263 for _, value := range data {
264 if value < lowerBound || value > upperBound {
265 outliers = append(outliers, value)
266 }
267 }
268
269 return outliers
270}
Real-World Applications:
- Quality Control: Process monitoring, defect detection, Six Sigma
- Finance: Risk assessment, portfolio analysis, market research
- Healthcare: Clinical trials, epidemiology, medical research
- Marketing: A/B testing, customer behavior analysis, segmentation
Complex Numbers and Signal Processing
Complex numbers are fundamental in signal processing, quantum mechanics, and electrical engineering.
1package main
2
3import (
4 "fmt"
5 "math"
6 "math/cmplx"
7)
8
9// run
10func main() {
11 fmt.Println("=== Complex Numbers and Signal Processing ===")
12
13 // 1. Basic complex number operations
14 fmt.Println("\n1. Basic Complex Number Operations:")
15 z1 := complex(3, 4) // 3 + 4i
16 z2 := complex(1, -2) // 1 - 2i
17
18 fmt.Printf("z1 = %.2f + %.2fi\n", real(z1), imag(z1))
19 fmt.Printf("z2 = %.2f + %.2fi\n", real(z2), imag(z2))
20
21 fmt.Printf("z1 + z2 = %.2f + %.2fi\n", real(z1+z2), imag(z1+z2))
22 fmt.Printf("z1 - z2 = %.2f + %.2fi\n", real(z1-z2), imag(z1-z2))
23 fmt.Printf("z1 * z2 = %.2f + %.2fi\n", real(z1*z2), imag(z1*z2))
24 fmt.Printf("z1 / z2 = %.2f + %.2fi\n", real(z1/z2), imag(z1/z2))
25
26 // 2. Complex number properties
27 fmt.Println("\n2. Complex Number Properties:")
28 magnitude := cmplx.Abs(z1)
29 phase := cmplx.Phase(z1)
30 conjugate := cmplx.Conj(z1)
31
32 fmt.Printf("Magnitude: %.4f\n", magnitude)
33 fmt.Printf("Phase): %.4f radians\n",
34 phase, phase*180/math.Pi)
35 fmt.Printf("Conjugate: %.2f + %.2fi\n", real(conjugate), imag(conjugate))
36
37 // 3. Polar form conversion
38 fmt.Println("\n3. Polar Form Conversion:")
39 r, theta := cmplx.Polar(z1)
40 fmt.Printf("Polar form: r = %.4f, θ = %.4f radians\n", r, theta)
41
42 zFromPolar := cmplx.Rect(r, theta)
43 fmt.Printf("Back to rectangular: %.2f + %.2fi\n", real(zFromPolar), imag(zFromPolar))
44
45 // 4. Complex exponential and logarithmic functions
46 fmt.Println("\n4. Complex Exponential and Logarithmic Functions:")
47
48 // Euler's formula: e^(iπ) + 1 = 0
49 euler := cmplx.Exp(1i * math.Pi)
50 fmt.Printf("e^(iπ) = %.6f + %.6fi\n", real(euler), imag(euler))
51 fmt.Printf("e^(iπ) + 1 = %.6f + %.6fi\n", real(euler+1), imag(euler+1))
52
53 // Complex logarithm
54 logZ1 := cmplx.Log(z1)
55 fmt.Printf("log(z1) = %.4f + %.4fi\n", real(logZ1), imag(logZ1))
56
57 // 5. Trigonometric functions with complex numbers
58 fmt.Println("\n5. Complex Trigonometric Functions:")
59 angle := math.Pi / 4
60 complexExp := cmplx.Exp(1i * angle)
61 cosAngle := cmplx.Cos(1i * angle)
62 sinAngle := cmplx.Sin(1i * angle)
63
64 fmt.Printf("e^(iπ/4) = %.4f + %.4fi\n", real(complexExp), imag(complexExp))
65 fmt.Printf("cos(iπ/4) = %.4f + %.4fi\n", real(cosAngle), imag(cosAngle))
66 fmt.Printf("sin(iπ/4) = %.4f + %.4fi\n", real(sinAngle), imag(sinAngle))
67
68 // 6. Signal processing example: DFT
69 fmt.Println("\n6. Discrete Fourier Transform:")
70 signal := []float64{1, 2, 3, 4, 3, 2, 1, 0}
71 spectrum := discreteFourierTransform(signal)
72
73 fmt.Printf("Signal: %v\n", signal)
74 fmt.Printf("DFT Spectrum: ")
75 for _, freq := range spectrum {
76 fmt.Printf("%.2f ", cmplx.Abs(freq))
77 }
78 fmt.Println()
79
80 // 7. Filter design example: Simple low-pass filter
81 fmt.Println("\n7. Simple Low-Pass Filter:")
82 filteredSignal := lowPassFilter(signal, 0.2)
83
84 fmt.Printf("Original: %v\n", signal)
85 fmt.Printf("Filtered: ")
86 for _, val := range filteredSignal {
87 fmt.Printf("%.2f ", val)
88 }
89 fmt.Println()
90}
91
92func discreteFourierTransform(signal []float64) []complex128 {
93 n := len(signal)
94 spectrum := make([]complex128, n)
95
96 for k := 0; k < n; k++ {
97 var sum complex128
98 for n := 0; n < len(signal); n++ {
99 angle := -2 * math.Pi * float64(k) * float64(n) / float64(len(signal))
100 sum += complex(signal[n], 0) * cmplx.Exp(1i*angle)
101 }
102 spectrum[k] = sum
103 }
104
105 return spectrum
106}
107
108func lowPassFilter(signal []float64, cutoffFreq float64) []float64 {
109 // Simple moving average filter
110 windowSize := int(1.0 / cutoffFreq)
111 if windowSize < 3 {
112 windowSize = 3
113 }
114 if windowSize > len(signal) {
115 windowSize = len(signal)
116 }
117
118 filtered := make([]float64, len(signal))
119
120 for i := range signal {
121 sum := 0.0
122 count := 0
123
124 for j := 0; j < windowSize; j++ {
125 idx := i - j
126 if idx >= 0 {
127 sum += signal[idx]
128 count++
129 }
130 }
131
132 if count > 0 {
133 filtered[i] = sum / float64(count)
134 } else {
135 filtered[i] = signal[i]
136 }
137 }
138
139 return filtered
140}
Real-World Applications:
- Signal Processing: Audio filtering, image processing, telecommunications
- Electrical Engineering: AC circuit analysis, power systems, control theory
- Physics: Quantum mechanics, wave propagation, electromagnetic fields
- Data Science: Time series analysis, frequency domain analysis, pattern recognition
Common Patterns and Pitfalls
Numerical Stability and Precision
1package main
2
3import (
4 "fmt"
5 "math"
6)
7
8// run
9func main() {
10 fmt.Println("=== Numerical Stability and Precision ===")
11
12 // 1. Floating-point precision issues
13 fmt.Println("\n1. Floating-Point Precision Issues:")
14
15 // Classic floating-point comparison problem
16 a := 0.1 + 0.2
17 b := 0.3
18
19 fmt.Printf("0.1 + 0.2 = %.18f\n", a)
20 fmt.Printf("0.3 = %.18f\n", b)
21 fmt.Printf("Direct equality check: %v\n", a == b)
22 fmt.Printf("Approximate equality check: %v\n", nearlyEqual(a, b, 1e-9))
23 fmt.Printf("Approximate equality check: %v\n", nearlyEqual(a, b, 1e-10))
24
25 // 2. Catastrophic cancellation
26 fmt.Println("\n2. Catastrophic Cancellation:")
27
28 // Bad approach: subtracting similar large numbers
29 x := 1.0000001
30 y := 1.0000000
31 badResult := x - y
32
33 // Good approach: reformulate the calculation
34 goodResult := /
35
36 fmt.Printf("x = %.10f, y = %.10f\n", x, y)
37 fmt.Printf("Bad result: %.15f\n", badResult)
38 fmt.Printf("Good result /): %.15f\n", goodResult)
39
40 // 3. Accumulation errors
41 fmt.Println("\n3. Accumulation Errors:")
42
43 // Bad: sequential sum
44 badSum := 0.0
45 numbers := []float64{1e16, 1, -1e16}
46 for _, num := range numbers {
47 badSum += num
48 }
49
50 // Good: Kahan summation algorithm
51 goodSum := kahanSum(numbers)
52
53 fmt.Printf("Numbers: %v\n", numbers)
54 fmt.Printf("Sequential sum: %.1f\n", badSum)
55 fmt.Printf("Kahan sum: %.1f\n", goodSum)
56 fmt.Printf("Expected: %.1f\n", 1.0)
57
58 // 4. Numerical differentiation
59 fmt.Println("\n4. Numerical Differentiation:")
60
61 f := func(x float64) float64 { return x * x } // f(x) = x²
62
63 h := 1e-6
64 x := 1.0
65
66 // Forward difference
67 forwardDiff := - f(x)) / h
68
69 // Central difference
70 centralDiff := - f(x-h)) /
71
72 fmt.Printf("f(x) = x² at x = %.1f\n", x)
73 fmt.Printf("Forward difference: %.8f\n", forwardDiff)
74 fmt.Printf("Central difference: %.8f\n", centralDiff)
75 fmt.Printf("Exact derivative: %.8f\n", 2*x)
76
77 // 5. Root finding algorithms
78 fmt.Println("\n5. Root Finding:")
79
80 // Newton's method for sqrt(2)
81 sqrt2 := newtonMethodSqrt(2.0, 10)
82 fmt.Printf("Newton's method sqrt(2): %.15f\n", sqrt2)
83 fmt.Printf("Math.Sqrt(2): %.15f\n", math.Sqrt(2))
84 fmt.Printf("Error: %.2e\n", math.Abs(sqrt2-math.Sqrt(2)))
85}
86
87func nearlyEqual(a, b, epsilon float64) bool {
88 if a == b {
89 return true
90 }
91
92 absA := math.Abs(a)
93 absB := math.Abs(b)
94 diff := math.Abs(a - b)
95
96 if a == 0 || b == 0 || absA+absB < math.SmallestNonzeroFloat64 {
97 return diff < epsilon*math.SmallestNonzeroFloat64
98 }
99
100 return diff/math.Min(absA+absB, math.MaxFloat64) < epsilon
101}
102
103func kahanSum(numbers []float64) float64 {
104 var sum, compensation float64
105
106 for _, num := range numbers {
107 y := num - compensation
108 t := sum + y
109 compensation = - y
110 sum = t
111 }
112
113 return sum
114}
115
116func newtonMethodSqrt(x float64, iterations int) float64 {
117 if x < 0 {
118 return math.NaN()
119 }
120
121 if x == 0 {
122 return 0
123 }
124
125 // Initial guess
126 guess := x
127
128 for i := 0; i < iterations; i++ {
129 // Newton's iteration: new_guess = / 2
130 guess = / 2
131 }
132
133 return guess
134}
Performance Optimization
1package main
2
3import (
4 "fmt"
5 "math"
6 "runtime"
7 "sync"
8 "time"
9)
10
11// run
12func main() {
13 fmt.Println("=== Mathematical Performance Optimization ===")
14
15 // 1. Vector operations
16 fmt.Println("\n1. Vector Operations:")
17
18 size := 1000000
19 a := make([]float64, size)
20 b := make([]float64, size)
21
22 // Initialize vectors
23 for i := 0; i < size; i++ {
24 a[i] = float64(i)
25 b[i] = float64(i * 2)
26 }
27
28 // Sequential dot product
29 start := time.Now()
30 sequentialResult := sequentialDotProduct(a, b)
31 sequentialTime := time.Since(start)
32
33 // Parallel dot product
34 start = time.Now()
35 parallelResult := parallelDotProduct(a, b)
36 parallelTime := time.Since(start)
37
38 fmt.Printf("Sequential dot product: %.0f\n", sequentialResult, sequentialTime)
39 fmt.Printf("Parallel dot product: %.0f\n", parallelResult, parallelTime)
40 fmt.Printf("Speedup: %.2fx\n", float64(sequentialTime)/float64(parallelTime))
41
42 // 2. Memoization for expensive functions
43 fmt.Println("\n2. Memoization:")
44
45 memoizedSin := memoize(math.Sin)
46
47 start = time.Now()
48 for i := 0; i < 10000; i++ {
49 math.Sin(1.23456789)
50 }
51 normalTime := time.Since(start)
52
53 start = time.Now()
54 for i := 0; i < 10000; i++ {
55 memoizedSin(1.23456789)
56 }
57 memoizedTime := time.Since(start)
58
59 fmt.Printf("Normal sin calls: %v\n", normalTime)
60 fmt.Printf("Memoized sin calls: %v\n", memoizedTime)
61 fmt.Printf("Speedup: %.2fx\n", float64(normalTime)/float64(memoizedTime))
62
63 // 3. Lookup tables for periodic functions
64 fmt.Println("\n3. Lookup Tables:")
65
66 // Create lookup table for sine
67 tableSize := 1000
68 sineTable := createSineLookupTable(tableSize)
69
70 x := 0.123456789
71
72 start = time.Now()
73 for i := 0; i < 100000; i++ {
74 math.Sin(x)
75 }
76 directTime := time.Since(start)
77
78 start = time.Now()
79 for i := 0; i < 100000; i++ {
80 lookupSine(x, sineTable)
81 }
82 lookupTime := time.Since(start)
83
84 fmt.Printf("Direct sine calculation: %v\n", directTime)
85 fmt.Printf("Lookup table sine: %v\n", lookupTime)
86 fmt.Printf("Speedup: %.2fx\n", float64(directTime)/float64(lookupTime))
87 fmt.Printf("Accuracy: %.6f\n", math.Abs(math.Sin(x)-lookupSine(x, sineTable)))
88
89 // 4. SIMD-like operations
90 fmt.Println("\n4. Vectorized Operations:")
91
92 vectors := make([][]float64, 4)
93 for i := range vectors {
94 vectors[i] = make([]float64, size)
95 for j := 0; j < size; j++ {
96 vectors[i][j] = float64(i*size + j)
97 }
98 }
99
100 start = time.Now()
101 sequentialVectorSum := sequentialVectorSum(vectors)
102 sequentialVectorTime := time.Since(start)
103
104 start = time.Now()
105 parallelVectorSum := parallelVectorSum(vectors)
106 parallelVectorTime := time.Since(start)
107
108 fmt.Printf("Sequential vector sum: %v\n", sequentialVectorTime)
109 fmt.Printf("Parallel vector sum: %v\n", parallelVectorTime)
110 fmt.Printf("Speedup: %.2fx\n", float64(sequentialVectorTime)/float64(parallelVectorTime))
111
112 fmt.Printf("Results match: %v\n", sequentialVectorSum == parallelVectorSum)
113}
114
115func sequentialDotProduct(a, b []float64) float64 {
116 sum := 0.0
117 for i := 0; i < len(a); i++ {
118 sum += a[i] * b[i]
119 }
120 return sum
121}
122
123func parallelDotProduct(a, b []float64) float64 {
124 numWorkers := runtime.NumCPU()
125 chunkSize := len(a) / numWorkers
126
127 results := make([]float64, numWorkers)
128 var wg sync.WaitGroup
129
130 for i := 0; i < numWorkers; i++ {
131 start := i * chunkSize
132 end := start + chunkSize
133 if i == numWorkers-1 {
134 end = len(a)
135 }
136
137 wg.Add(1)
138 go func(workerID, start, end int) {
139 defer wg.Done()
140
141 partialSum := 0.0
142 for j := start; j < end; j++ {
143 partialSum += a[j] * b[j]
144 }
145 results[workerID] = partialSum
146 }(i, start, end)
147 }
148
149 wg.Wait()
150
151 totalSum := 0.0
152 for _, result := range results {
153 totalSum += result
154 }
155
156 return totalSum
157}
158
159func memoize(f func(float64) float64) func(float64) float64 {
160 cache := make(map[float64]float64)
161 var mutex sync.RWMutex
162
163 return func(x float64) float64 {
164 mutex.RLock()
165 if result, ok := cache[x]; ok {
166 mutex.RUnlock()
167 return result
168 }
169 mutex.RUnlock()
170
171 result := f(x)
172
173 mutex.Lock()
174 cache[x] = result
175 mutex.Unlock()
176
177 return result
178 }
179}
180
181func createSineLookupTable(size int) []float64 {
182 table := make([]float64, size)
183 for i := 0; i < size; i++ {
184 angle := 2 * math.Pi * float64(i) / float64(size)
185 table[i] = math.Sin(angle)
186 }
187 return table
188}
189
190func lookupSine(x float64, table []float64) float64 {
191 // Normalize angle to [0, 2π]
192 x = math.Mod(x, 2*math.Pi)
193 if x < 0 {
194 x += 2 * math.Pi
195 }
196
197 // Find nearest table entry
198 index := int(x * float64(len(table)) /)
199 if index >= len(table) {
200 index = len(table) - 1
201 }
202
203 return table[index]
204}
205
206func sequentialVectorSum(vectors [][]float64) float64 {
207 sum := 0.0
208 for _, vector := range vectors {
209 for _, value := range vector {
210 sum += value
211 }
212 }
213 return sum
214}
215
216func parallelVectorSum(vectors [][]float64) float64 {
217 var wg sync.WaitGroup
218 results := make(chan float64, len(vectors))
219
220 for _, vector := range vectors {
221 wg.Add(1)
222 go func(v []float64) {
223 defer wg.Done()
224 partialSum := 0.0
225 for _, value := range v {
226 partialSum += value
227 }
228 results <- partialSum
229 }(vector)
230 }
231
232 wg.Wait()
233 close(results)
234
235 totalSum := 0.0
236 for result := range results {
237 totalSum += result
238 }
239
240 return totalSum
241}
Integration and Mastery
Scientific Computing Application
1package main
2
3import (
4 "fmt"
5 "math"
6 "sort"
7)
8
9// run
10func main() {
11 fmt.Println("=== Scientific Computing Application ===")
12
13 // Simulate population dynamics with Lotka-Volterra equations
14 fmt.Println("\n1. Population Dynamics Simulation:")
15
16 // Initial conditions
17 prey := []float64{100} // Initial prey population
18 predator := []float64{20} // Initial predator population
19
20 // Model parameters
21 alpha := 1.0 // Prey growth rate
22 beta := 0.1 // Predation rate
23 delta := 0.075 // Predator efficiency
24 gamma := 1.5 // Predator death rate
25
26 dt := 0.01 // Time step
27 steps := 1000 // Number of steps
28
29 // Simulate
30 for i := 1; i < steps; i++ {
31 x := prey[i-1] // Current prey
32 y := predator[i-1] // Current predator
33
34 // Lotka-Volterra equations
35 dxdt := alpha*x - beta*x*y
36 dydt := delta*x*y - gamma*y
37
38 // Euler's method
39 newPrey := x + dxdt*dt
40 newPredator := y + dydt*dt
41
42 // Ensure populations don't go negative
43 if newPrey < 0 {
44 newPrey = 0
45 }
46 if newPredator < 0 {
47 newPredator = 0
48 }
49
50 prey = append(prey, newPrey)
51 predator = append(predator, newPredator)
52 }
53
54 fmt.Printf("Simulation complete. Steps: %d\n", steps)
55 fmt.Printf("Final prey population: %.2f\n", prey[len(prey)-1])
56 fmt.Printf("Final predator population: %.2f\n", predator[len(predator)-1])
57
58 // Calculate statistics
59 preyStats := calculateStats(prey)
60 predatorStats := calculateStats(predator)
61
62 fmt.Printf("\nPrey statistics:\n")
63 fmt.Printf(" Mean: %.2f\n", preyStats.mean)
64 fmt.Printf(" Std Dev: %.2f\n", preyStats.stdDev)
65 fmt.Printf(" Min: %.2f\n", preyStats.min)
66 fmt.Printf(" Max: %.2f\n", preyStats.max)
67
68 fmt.Printf("\nPredator statistics:\n")
69 fmt.Printf(" Mean: %.2f\n", predatorStats.mean)
70 fmt.Printf(" Std Dev: %.2f\n", predatorStats.stdDev)
71 fmt.Printf(" Min: %.2f\n", predatorStats.min)
72 fmt.Printf(" Max: %.2f\n", predatorStats.max)
73
74 // Monte Carlo simulation for pi estimation
75 fmt.Println("\n2. Monte Carlo Pi Estimation:")
76
77 numPoints := 100000
78 piEstimate := monteCarloPi(numPoints)
79 fmt.Printf("Estimated π: %.8f\n", piEstimate)
80 fmt.Printf("Actual π: %.8f\n", math.Pi)
81 fmt.Printf("Error: %.8f\n", math.Abs(piEstimate-math.Pi))
82 fmt.Printf("Relative error: %.6f%%\n", math.Abs(piEstimate-math.Pi)/math.Pi*100)
83
84 // Simple heat diffusion simulation
85 fmt.Println("\n3. Heat Diffusion Simulation:")
86
87 size := 20
88 iterations := 100
89
90 // Initialize grid with hot spot in center
91 grid := make([][]float64, size)
92 for i := range grid {
93 grid[i] = make([]float64, size)
94 }
95
96 // Set initial conditions
97 center := size / 2
98 grid[center][center] = 100.0 // Hot spot
99
100 // Simulate heat diffusion
101 for iter := 0; iter < iterations; iter++ {
102 grid = diffuseHeat(grid, 0.1)
103 }
104
105 // Display final temperature distribution
106 fmt.Printf("Heat distribution after %d iterations:\n", iterations)
107 displayHeatMap(grid)
108}
109
110type Statistics struct {
111 mean float64
112 stdDev float64
113 min float64
114 max float64
115}
116
117func calculateStats(data []float64) Statistics {
118 n := float64(len(data))
119
120 // Calculate mean
121 sum := 0.0
122 for _, value := range data {
123 sum += value
124 }
125 mean := sum / n
126
127 // Calculate standard deviation
128 sumSquares := 0.0
129 for _, value := range data {
130 diff := value - mean
131 sumSquares += diff * diff
132 }
133 stdDev := math.Sqrt(sumSquares / n)
134
135 // Find min and max
136 min := data[0]
137 max := data[0]
138 for _, value := range data {
139 if value < min {
140 min = value
141 }
142 if value > max {
143 max = value
144 }
145 }
146
147 return Statistics{mean, stdDev, min, max}
148}
149
150func monteCarloPi(numPoints int) float64 {
151 insideCircle := 0
152
153 for i := 0; i < numPoints; i++ {
154 // Generate random point in unit square
155 x := 2.0*float64(i%1000)/1000 - 1.0 // Simple pseudo-random
156 y := 2.0*float64((i/1000)%1000)/1000 - 1.0
157
158 // Check if point is inside unit circle
159 if x*x+y*y <= 1.0 {
160 insideCircle++
161 }
162 }
163
164 // Pi ≈ 4 *
165 return 4.0 * float64(insideCircle) / float64(numPoints)
166}
167
168func diffuseHeat(grid [][]float64, diffusivity float64) [][]float64 {
169 size := len(grid)
170 newGrid := make([][]float64, size)
171
172 for i := range newGrid {
173 newGrid[i] = make([]float64, size)
174 }
175
176 // Apply heat diffusion equation
177 for i := 1; i < size-1; i++ {
178 for j := 1; j < size-1; j++ {
179 // Average of neighboring cells
180 neighbors := grid[i-1][j] + grid[i+1][j] + grid[i][j-1] + grid[i][j+1]
181 newGrid[i][j] = grid[i][j] + diffusivity*(neighbors/4.0 - grid[i][j])
182 }
183 }
184
185 return newGrid
186}
187
188func displayHeatMap(grid [][]float64) {
189 // Extract all temperatures for scaling
190 var temps []float64
191 for i := range grid {
192 for j := range grid[i] {
193 temps = append(temps, grid[i][j])
194 }
195 }
196 sort.Float64s(temps)
197 min := temps[0]
198 max := temps[len(temps)-1]
199
200 // Simple ASCII heat map
201 for i := range grid {
202 for j := range grid[i] {
203 temp := grid[i][j]
204 normalized := /
205
206 var char string
207 switch {
208 case normalized < 0.2:
209 char = " "
210 case normalized < 0.4:
211 char = "░"
212 case normalized < 0.6:
213 char = "▒"
214 case normalized < 0.8:
215 char = "▓"
216 default:
217 char = "█"
218 }
219 fmt.Printf("%s", char)
220 }
221 fmt.Println()
222 }
223}
Advanced Topics
Big Number Arithmetic
For financial applications and cryptography, arbitrary-precision arithmetic is essential.
1package main
2
3import (
4 "fmt"
5 "math"
6 "math/big"
7)
8
9// run
10func main() {
11 fmt.Println("=== Big Number Arithmetic ===")
12
13 // 1. Basic big number operations
14 fmt.Println("\n1. Basic Big Number Operations:")
15
16 a := big.NewInt(123456789012345678)
17 b := big.NewInt(987654321098765432)
18
19 sum := new(big.Int).Add(a, b)
20 diff := new(big.Int).Sub(b, a)
21 product := new(big.Int).Mul(a, b)
22
23 fmt.Printf("a = %v\n", a)
24 fmt.Printf("b = %v\n", b)
25 fmt.Printf("a + b = %v\n", sum)
26 fmt.Printf("b - a = %v\n", diff)
27 fmt.Printf("a * b = %v\n", product)
28
29 // 2. Large factorial calculation
30 fmt.Println("\n2. Large Factorial:")
31
32 n := 100
33 fact := factorial(n)
34 fmt.Printf("%d! = %v\n", n, fact)
35 fmt.Printf("Number of digits: %d\n", len(fact.String()))
36
37 // 3. Modular arithmetic
38 fmt.Println("\n3. Modular Arithmetic:")
39
40 base := big.NewInt(2)
41 exp := big.NewInt(1000)
42 mod := big.NewInt(1000000007)
43
44 result := new(big.Int).Exp(base, exp, mod)
45 fmt.Printf("2^1000 mod 1000000007 = %v\n", result)
46
47 // 4. Big float precision arithmetic
48 fmt.Println("\n4. Big Float Precision Arithmetic:")
49
50 x := new(big.Float).SetPrec(100) // 100-bit precision
51 x.SetString("3.141592653589793238462643383279502884197")
52
53 y := new(big.Float).SetPrec(100)
54 y.SetString("2.718281828459045235360287471352662497757")
55
56 sum_f := new(big.Float).Add(x, y)
57 fmt.Printf("π + e = %v\n", sum_f)
58
59 // 5. Computing square roots with arbitrary precision
60 fmt.Println("\n5. Square Root Computation:")
61
62 n_big := big.NewFloat(2.0)
63 sqrt2 := computeSquareRoot(n_big, 50)
64 fmt.Printf("√2 (50-bit precision) = %v\n", sqrt2)
65 fmt.Printf("Standard √2 = %.15f\n", math.Sqrt(2))
66}
67
68func factorial(n int) *big.Int {
69 result := big.NewInt(1)
70 for i := 2; i <= n; i++ {
71 result.Mul(result, big.NewInt(int64(i)))
72 }
73 return result
74}
75
76func computeSquareRoot(x *big.Float, prec uint) *big.Float {
77 result := new(big.Float).SetPrec(prec)
78 result.SetFloat64(1.0) // Initial guess
79
80 for i := 0; i < 100; i++ {
81 prev := new(big.Float).Copy(result)
82 x_over_result := new(big.Float).Quo(x, result)
83 result = new(big.Float).Add(result, x_over_result)
84 result.Mul(result, new(big.Float).SetFloat64(0.5))
85
86 // Check convergence
87 diff := new(big.Float).Sub(result, prev)
88 if diff.Cmp(new(big.Float).SetFloat64(1e-100)) < 0 {
89 break
90 }
91 }
92
93 return result
94}
Matrix Operations and Linear Algebra
Matrix operations are fundamental for scientific computing, machine learning, and computer graphics.
1package main
2
3import (
4 "fmt"
5 "math"
6)
7
8// run
9func main() {
10 fmt.Println("=== Matrix Operations ===")
11
12 // 1. Matrix creation and multiplication
13 fmt.Println("\n1. Matrix Multiplication:")
14
15 a := [][]float64{
16 {1, 2, 3},
17 {4, 5, 6},
18 }
19
20 b := [][]float64{
21 {7, 8},
22 {9, 10},
23 {11, 12},
24 }
25
26 c := matrixMultiply(a, b)
27 fmt.Printf("Matrix A (2x3):\n")
28 printMatrix(a)
29 fmt.Printf("Matrix B (3x2):\n")
30 printMatrix(b)
31 fmt.Printf("A × B (2x2):\n")
32 printMatrix(c)
33
34 // 2. Matrix transpose
35 fmt.Println("\n2. Matrix Transpose:")
36
37 transposed := matrixTranspose(a)
38 fmt.Printf("Transpose of A:\n")
39 printMatrix(transposed)
40
41 // 3. Determinant calculation (for square matrix)
42 fmt.Println("\n3. Determinant Calculation:")
43
44 matrix3x3 := [][]float64{
45 {1, 2, 3},
46 {4, 5, 6},
47 {7, 8, 9},
48 }
49
50 det := determinant(matrix3x3)
51 fmt.Printf("Determinant of 3x3 matrix: %.2f\n", det)
52
53 // 4. Eigenvalues (power method for largest eigenvalue)
54 fmt.Println("\n4. Eigenvalue (Largest):")
55
56 symmetricMatrix := [][]float64{
57 {4, 1},
58 {1, 3},
59 }
60
61 eigenvalue := powerMethod(symmetricMatrix, 100)
62 fmt.Printf("Largest eigenvalue: %.4f\n", eigenvalue)
63
64 // 5. Matrix inversion for 2x2
65 fmt.Println("\n5. Matrix Inversion (2x2):")
66
67 matrix2x2 := [][]float64{
68 {1, 2},
69 {3, 4},
70 }
71
72 inverse := invertMatrix2x2(matrix2x2)
73 fmt.Printf("Original:\n")
74 printMatrix(matrix2x2)
75 fmt.Printf("Inverse:\n")
76 printMatrix(inverse)
77}
78
79func matrixMultiply(a, b [][]float64) [][]float64 {
80 rows := len(a)
81 cols := len(b[0])
82 common := len(b)
83
84 result := make([][]float64, rows)
85 for i := 0; i < rows; i++ {
86 result[i] = make([]float64, cols)
87 for j := 0; j < cols; j++ {
88 sum := 0.0
89 for k := 0; k < common; k++ {
90 sum += a[i][k] * b[k][j]
91 }
92 result[i][j] = sum
93 }
94 }
95 return result
96}
97
98func matrixTranspose(m [][]float64) [][]float64 {
99 rows := len(m)
100 cols := len(m[0])
101
102 result := make([][]float64, cols)
103 for i := 0; i < cols; i++ {
104 result[i] = make([]float64, rows)
105 for j := 0; j < rows; j++ {
106 result[i][j] = m[j][i]
107 }
108 }
109 return result
110}
111
112func determinant(m [][]float64) float64 {
113 n := len(m)
114 if n == 1 {
115 return m[0][0]
116 }
117 if n == 2 {
118 return m[0][0]*m[1][1] - m[0][1]*m[1][0]
119 }
120
121 det := 0.0
122 for i := 0; i < n; i++ {
123 minor := getMinor(m, 0, i)
124 sign := 1.0
125 if i%2 == 1 {
126 sign = -1.0
127 }
128 det += sign * m[0][i] * determinant(minor)
129 }
130 return det
131}
132
133func getMinor(m [][]float64, row, col int) [][]float64 {
134 n := len(m)
135 minor := make([][]float64, n-1)
136
137 minorRow := 0
138 for i := 0; i < n; i++ {
139 if i == row {
140 continue
141 }
142 minor[minorRow] = make([]float64, n-1)
143 minorCol := 0
144 for j := 0; j < n; j++ {
145 if j == col {
146 continue
147 }
148 minor[minorRow][minorCol] = m[i][j]
149 minorCol++
150 }
151 minorRow++
152 }
153 return minor
154}
155
156func powerMethod(m [][]float64, iterations int) float64 {
157 n := len(m)
158 v := make([]float64, n)
159 for i := 0; i < n; i++ {
160 v[i] = 1.0
161 }
162
163 for iter := 0; iter < iterations; iter++ {
164 // Matrix-vector multiplication
165 newV := make([]float64, n)
166 for i := 0; i < n; i++ {
167 for j := 0; j < n; j++ {
168 newV[i] += m[i][j] * v[j]
169 }
170 }
171
172 // Normalize
173 norm := 0.0
174 for _, val := range newV {
175 norm += val * val
176 }
177 norm = math.Sqrt(norm)
178
179 for i := 0; i < n; i++ {
180 v[i] = newV[i] / norm
181 }
182 }
183
184 // Calculate Rayleigh quotient
185 mv := make([]float64, n)
186 for i := 0; i < n; i++ {
187 for j := 0; j < n; j++ {
188 mv[i] += m[i][j] * v[j]
189 }
190 }
191
192 eigenvalue := 0.0
193 vv := 0.0
194 for i := 0; i < n; i++ {
195 eigenvalue += v[i] * mv[i]
196 vv += v[i] * v[i]
197 }
198
199 return eigenvalue / vv
200}
201
202func invertMatrix2x2(m [][]float64) [][]float64 {
203 det := m[0][0]*m[1][1] - m[0][1]*m[1][0]
204
205 if math.Abs(det) < 1e-10 {
206 return nil // Singular matrix
207 }
208
209 return [][]float64{
210 {m[1][1] / det, -m[0][1] / det},
211 {-m[1][0] / det, m[0][0] / det},
212 }
213}
214
215func printMatrix(m [][]float64) {
216 for _, row := range m {
217 for _, val := range row {
218 fmt.Printf("% 8.2f ", val)
219 }
220 fmt.Println()
221 }
222 fmt.Println()
223}
Practice Exercises
Exercise 1: Financial Analysis Library
Learning Objectives: Master practical financial mathematics, statistical analysis, and algorithm implementation for real-world financial scenarios.
Real-World Context: Financial analysis is critical in trading, risk management, investment planning, and portfolio optimization. This exercise teaches you to implement core financial calculations used in trading systems, investment platforms, and risk assessment tools. Companies like Bloomberg, Goldman Sachs, and Robinhood use similar algorithms for their financial products.
Difficulty: Intermediate | Time Estimate: 3-4 hours
Description: Create a comprehensive financial analysis library that calculates various financial metrics, performs portfolio analysis, and implements basic trading algorithms. The library should handle real-time data processing, risk calculations, and investment recommendations.
Requirements:
- Portfolio Management: Track multiple assets, calculate portfolio value and returns
- Risk Metrics: Value at Risk, Sharpe ratio, Beta calculation
- Technical Analysis: Moving averages, RSI, MACD indicators
- Option Pricing: Black-Scholes model for European options
- Monte Carlo Simulation: Price path simulation for option pricing
- Performance Tracking: Daily returns, volatility, drawdown calculations
- Optimization: Portfolio optimization using modern portfolio theory
- Data Validation: Handle missing data, outliers, and data quality issues
- Caching: Optimize performance with result caching and memoization
- Error Handling: Comprehensive error handling for financial calculations
Solution
1package main
2
3import (
4 "fmt"
5 "math"
6 "sort"
7 "time"
8)
9
10// Portfolio represents a collection of financial assets
11type Portfolio struct {
12 Assets map[string]Asset
13 Cash float64
14}
15
16// Asset represents a single financial asset
17type Asset struct {
18 Symbol string
19 Quantity float64
20 Price float64
21 Beta float64
22 Volatility float64
23}
24
25// HistoricalPrice stores price history data
26type HistoricalPrice struct {
27 Date time.Time
28 Open float64
29 High float64
30 Low float64
31 Close float64
32 Volume int64
33}
34
35// PortfolioMetrics contains calculated portfolio metrics
36type PortfolioMetrics struct {
37 TotalValue float64
38 TotalReturn float64
39 DailyReturn float64
40 Volatility float64
41 SharpeRatio float64
42 ValueAtRisk float64
43 Beta float64
44 MaxDrawdown float64
45 AssetAllocation map[string]float64
46}
47
48// TechnicalIndicators contains technical analysis results
49type TechnicalIndicators struct {
50 Symbol string
51 SMA5 float64 // 5-day simple moving average
52 SMA20 float64 // 20-day simple moving average
53 RSI float64 // Relative Strength Index
54 MACD float64 // MACD line
55 Signal float64 // Signal line
56}
57
58// Option represents a financial option
59type Option struct {
60 Type string // "call" or "put"
61 Underlying string // Underlying asset symbol
62 Strike float64 // Strike price
63 Expiry time.Time
64 Price float64 // Current option price
65}
66
67// NewPortfolio creates a new portfolio
68func NewPortfolio(initialCash float64) *Portfolio {
69 return &Portfolio{
70 Assets: make(map[string]Asset),
71 Cash: initialCash,
72 }
73}
74
75// AddAsset adds an asset to portfolio
76func AddAsset(symbol string, quantity, price, beta, volatility float64) {
77 if existing, exists := p.Assets[symbol]; exists {
78 // Update existing asset
79 totalQuantity := existing.Quantity + quantity
80 totalCost := existing.Quantity*existing.Price + quantity*price
81 avgPrice := totalCost / totalQuantity
82
83 p.Assets[symbol] = Asset{
84 Symbol: symbol,
85 Quantity: totalQuantity,
86 Price: avgPrice,
87 Beta: beta,
88 Volatility: volatility,
89 }
90 } else {
91 p.Assets[symbol] = Asset{
92 Symbol: symbol,
93 Quantity: quantity,
94 Price: price,
95 Beta: beta,
96 Volatility: volatility,
97 }
98 }
99
100 p.Cash -= quantity * price
101}
102
103// UpdatePrices updates all asset prices
104func UpdatePrices(prices map[string]float64) {
105 for symbol, asset := range p.Assets {
106 if price, exists := prices[symbol]; exists {
107 asset.Price = price
108 p.Assets[symbol] = asset
109 }
110 }
111}
112
113// CalculateMetrics calculates comprehensive portfolio metrics
114func CalculateMetrics(prices []float64, riskFreeRate float64) PortfolioMetrics {
115 totalValue := p.GetTotalValue()
116 metrics := PortfolioMetrics{
117 TotalValue: totalValue,
118 AssetAllocation: make(map[string]float64),
119 }
120
121 // Calculate asset allocation
122 for symbol, asset := range p.Assets {
123 assetValue := asset.Quantity * asset.Price
124 allocation := assetValue / totalValue
125 metrics.AssetAllocation[symbol] = allocation
126 }
127
128 // Calculate returns and volatility from price history
129 if len(prices) > 1 {
130 returns := calculateReturns(prices)
131 metrics.Volatility = calculateVolatility(returns)
132 metrics.DailyReturn = returns[len(returns)-1]
133 metrics.MaxDrawdown = calculateMaxDrawdown(prices)
134
135 // Calculate Sharpe ratio
136 if metrics.Volatility > 0 {
137 metrics.SharpeRatio = / metrics.Volatility
138 }
139
140 // Calculate Value at Risk
141 metrics.ValueAtRisk = calculateVaR(returns, 0.95)
142 }
143
144 // Calculate portfolio beta
145 totalBeta := 0.0
146 for symbol, allocation := range metrics.AssetAllocation {
147 if asset, exists := p.Assets[symbol]; exists {
148 totalBeta += allocation * asset.Beta
149 }
150 }
151 metrics.Beta = totalBeta
152
153 return metrics
154}
155
156// GetTotalValue calculates total portfolio value
157func GetTotalValue() float64 {
158 total := p.Cash
159 for _, asset := range p.Assets {
160 total += asset.Quantity * asset.Price
161 }
162 return total
163}
164
165// calculateReturns calculates daily returns from price series
166func calculateReturns(prices []float64) []float64 {
167 if len(prices) < 2 {
168 return nil
169 }
170
171 returns := make([]float64, len(prices)-1)
172 for i := 1; i < len(prices); i++ {
173 returns[i-1] = / prices[i-1]
174 }
175 return returns
176}
177
178// calculateVolatility calculates standard deviation of returns
179func calculateVolatility(returns []float64) float64 {
180 if len(returns) == 0 {
181 return 0
182 }
183
184 mean := 0.0
185 for _, ret := range returns {
186 mean += ret
187 }
188 mean /= float64(len(returns))
189
190 variance := 0.0
191 for _, ret := range returns {
192 diff := ret - mean
193 variance += diff * diff
194 }
195 variance /= float64(len(returns))
196
197 return math.Sqrt(variance)
198}
199
200// calculateMaxDrawdown calculates maximum drawdown
201func calculateMaxDrawdown(prices []float64) float64 {
202 if len(prices) < 2 {
203 return 0
204 }
205
206 maxDrawdown := 0.0
207 peak := prices[0]
208
209 for _, price := range prices {
210 if price > peak {
211 peak = price
212 }
213
214 drawdown := / peak
215 if drawdown > maxDrawdown {
216 maxDrawdown = drawdown
217 }
218 }
219
220 return maxDrawdown
221}
222
223// calculateVaR calculates Value at Risk
224func calculateVaR(returns []float64, confidence float64) float64 {
225 if len(returns) == 0 {
226 return 0
227 }
228
229 // Sort returns
230 sorted := make([]float64, len(returns))
231 copy(sorted, returns)
232 sort.Float64s(sorted)
233
234 // Find return at confidence level
235 index := int((1 - confidence) * float64(len(sorted)))
236 if index >= len(sorted) {
237 index = len(sorted) - 1
238 }
239
240 return -sorted[index] // Return negative as loss
241}
242
243// CalculateSMA calculates Simple Moving Average
244func CalculateSMA(prices []float64, period int) float64 {
245 if len(prices) < period {
246 return 0
247 }
248
249 sum := 0.0
250 for i := len(prices) - period; i < len(prices); i++ {
251 sum += prices[i]
252 }
253 return sum / float64(period)
254}
255
256// CalculateRSI calculates Relative Strength Index
257func CalculateRSI(prices []float64, period int) float64 {
258 if len(prices) < period+1 {
259 return 50.0 // Neutral
260 }
261
262 var gains, losses float64
263 for i := len(prices) - period; i < len(prices); i++ {
264 change := prices[i] - prices[i-1]
265 if change > 0 {
266 gains += change
267 } else {
268 losses -= change
269 }
270 }
271
272 avgGain := gains / float64(period)
273 avgLoss := losses / float64(period)
274
275 if avgLoss == 0 {
276 return 100.0
277 }
278
279 rs := avgGain / avgLoss
280 rsi := 100.0 -)
281 return rsi
282}
283
284// BlackScholesCall prices a European call option using Black-Scholes model
285func BlackScholesCall(S, K, r, sigma, T float64) float64 {
286 // S: Current stock price
287 // K: Strike price
288 // r: Risk-free interest rate
289 // sigma: Volatility
290 // T: Time to expiration
291
292 if T <= 0 || sigma <= 0 {
293 return 0
294 }
295
296 d1 := +*T) /)
297 d2 := d1 - sigma*math.Sqrt(T)
298
299 // Use normal distribution approximation
300 callPrice := S*normalCDF(d1) - K*math.Exp(-r*T)*normalCDF(d2)
301 return callPrice
302}
303
304// BlackScholesPut prices a European put option using Black-Scholes model
305func BlackScholesPut(S, K, r, sigma, T float64) float64 {
306 d1 := +*T) /)
307 d2 := d1 - sigma*math.Sqrt(T)
308
309 putPrice := K*math.Exp(-r*T)*normalCDF(-d2) - S*normalCDF(-d1)
310 return putPrice
311}
312
313// normalCDF approximates the cumulative distribution function of standard normal
314func normalCDF(x float64) float64 {
315 // Abramowitz and Stegun formula 7.1.26
316 a1 := 0.254829592
317 a2 := -0.284496736
318 a3 := 1.421413741
319 a4 := -1.453152027
320 a5 := 1.061405429
321 p := 0.3275911
322
323 sign := 1.0
324 if x < 0 {
325 sign = -1.0
326 }
327 x = math.Abs(x)
328
329 t := 1.0 /
330 y := 1.0 -*t) + a3)*t + a2)*t + a1)*t*math.Exp(-x*x)
331
332 return 0.5 *
333}
334
335// MonteCarloOptionPrice prices an option using Monte Carlo simulation
336func MonteCarloOptionPrice(S, K, r, sigma, T float64, optionType string, simulations int) float64 {
337 if simulations <= 0 {
338 simulations = 10000
339 }
340
341 sumPayoffs := 0.0
342 dt := T / 252.0 // Daily steps
343
344 for i := 0; i < simulations; i++ {
345 stockPrice := S
346 currentT := 0.0
347
348 for currentT < T {
349 // Generate random shock using Box-Muller transform
350 z := generateNormalRandom()
351 stockPrice = stockPrice * math.Exp((r-0.5*sigma*sigma)*dt + sigma*math.Sqrt(dt)*z)
352 currentT += dt
353 }
354
355 // Calculate payoff
356 payoff := 0.0
357 if optionType == "call" {
358 payoff = math.Max(0, stockPrice-K)
359 } else if optionType == "put" {
360 payoff = math.Max(0, K-stockPrice)
361 }
362
363 sumPayoffs += payoff
364 }
365
366 // Discount expected payoff
367 expectedPayoff := sumPayoffs / float64(simulations)
368 optionPrice := math.Exp(-r*T) * expectedPayoff
369
370 return optionPrice
371}
372
373// generateNormalRandom generates a standard normal random variable
374func generateNormalRandom() float64 {
375 // In practice, use a proper random number generator
376 // This is a simplified version using sine function for demonstration
377 return math.Sin(float64(time.Now().UnixNano()%1000) / 100.0)
378}
379
380// OptimizePortfolio finds optimal portfolio weights using Markowitz optimization
381func OptimizePortfolio(expectedReturns []float64, covarianceMatrix [][]float64, riskFreeRate float64) {
382 n := len(expectedReturns)
383
384 // Simplified optimization - equal weight portfolio
385 // In practice, use quadratic programming solver
386 weights := make([]float64, n)
387 for i := range weights {
388 weights[i] = 1.0 / float64(n)
389 }
390
391 // Calculate portfolio metrics
392 portfolioReturn := 0.0
393 for i, ret := range expectedReturns {
394 portfolioReturn += weights[i] * ret
395 }
396
397 portfolioVariance := 0.0
398 for i := 0; i < n; i++ {
399 for j := 0; j < n; j++ {
400 portfolioVariance += weights[i] * weights[j] * covarianceMatrix[i][j]
401 }
402 }
403 portfolioRisk := math.Sqrt(portfolioVariance)
404
405 return weights, portfolioReturn, portfolioRisk
406}
407
408func main() {
409 // Example usage
410 fmt.Println("=== Financial Analysis Library Demo ===")
411
412 // Create portfolio
413 portfolio := NewPortfolio(10000.0)
414
415 // Add assets
416 portfolio.AddAsset("AAPL", 100, 150.0, 1.2, 0.25)
417 portfolio.AddAsset("GOOGL", 50, 2500.0, 1.1, 0.22)
418 portfolio.AddAsset("MSFT", 75, 300.0, 1.0, 0.20)
419
420 // Update prices
421 prices := map[string]float64{
422 "AAPL": 155.0,
423 "GOOGL": 2550.0,
424 "MSFT": 310.0,
425 }
426 portfolio.UpdatePrices(prices)
427
428 // Calculate metrics
429 priceHistory := []float64{100000, 102000, 101000, 103000, 105000, 104000, 106000}
430 metrics := portfolio.CalculateMetrics(priceHistory, 0.02)
431
432 fmt.Printf("Portfolio Total Value: $%.2f\n", metrics.TotalValue)
433 fmt.Printf("Daily Return: %.2f%%\n", metrics.DailyReturn*100)
434 fmt.Printf("Volatility: %.2f%%\n", metrics.Volatility*100)
435 fmt.Printf("Sharpe Ratio: %.2f\n", metrics.SharpeRatio)
436 fmt.Printf("Value at Risk: %.2f%%\n", metrics.ValueAtRisk*100)
437 fmt.Printf("Beta: %.2f\n", metrics.Beta)
438
439 fmt.Println("\nAsset Allocation:")
440 for symbol, allocation := range metrics.AssetAllocation {
441 fmt.Printf("%s: %.2f%%\n", symbol, allocation*100)
442 }
443
444 // Option pricing example
445 fmt.Println("\n=== Option Pricing ===")
446 callPrice := BlackScholesCall(100.0, 105.0, 0.05, 0.2, 0.25)
447 putPrice := BlackScholesPut(100.0, 105.0, 0.05, 0.2, 0.25)
448
449 fmt.Printf("Call Option Price: $%.2f\n", callPrice)
450 fmt.Printf("Put Option Price: $%.2f\n", putPrice)
451
452 // Monte Carlo pricing
453 mcCallPrice := MonteCarloOptionPrice(100.0, 105.0, 0.05, 0.2, 0.25, "call", 1000)
454 fmt.Printf("Monte Carlo Call Price: $%.2f\n", mcCallPrice)
455
456 // Technical indicators
457 fmt.Println("\n=== Technical Analysis ===")
458 stockPrices := []float64{100, 102, 101, 103, 105, 104, 106, 108, 107, 109}
459
460 sma5 := CalculateSMA(stockPrices, 5)
461 sma20 := CalculateSMA(stockPrices, 20)
462 rsi := CalculateRSI(stockPrices, 14)
463
464 fmt.Printf("5-day SMA: %.2f\n", sma5)
465 fmt.Printf("20-day SMA: %.2f\n", sma20)
466 fmt.Printf("RSI: %.2f\n", rsi)
467}
Exercise 2: Statistical Data Analyzer
Learning Objectives: Implement comprehensive statistical analysis tools for real-world data science applications.
Real-World Context: Data scientists and analysts use statistical tools daily to understand data patterns, detect anomalies, and make data-driven decisions. Building statistical analysis libraries demonstrates core competencies needed in data science, machine learning operations, and business intelligence roles.
Difficulty: Intermediate | Time Estimate: 2-3 hours
Description: Create a statistical analysis tool that processes datasets, calculates various statistical measures, detects outliers, and generates statistical summaries.
Requirements:
- Descriptive Statistics: Mean, median, mode, range, variance, standard deviation, skewness, kurtosis
- Data Quality: Handling missing values, data validation, outlier detection
- Correlation Analysis: Compute correlations between variables
- Distribution Fitting: Fit data to normal distribution and test goodness of fit
- Hypothesis Testing: T-tests, chi-square tests
- Data Visualization: Generate simple ASCII histograms and summaries
- Performance: Efficient computation for large datasets
- Error Handling: Handle edge cases and invalid inputs
Solution Outline
Implement functions for:
- Data loading and preprocessing
- Descriptive statistics calculations
- Outlier detection using IQR and Z-score methods
- Correlation matrix computation
- Hypothesis testing functions
- Summary report generation with formatted output
Exercise 3: Scientific Simulation Framework
Learning Objectives: Build reusable frameworks for scientific simulations and numerical modeling.
Real-World Context: Scientific simulations power industries from weather forecasting to pharmaceutical research. This exercise teaches you to build robust simulation frameworks used in research institutions, tech companies, and consulting firms.
Difficulty: Advanced | Time Estimate: 4-5 hours
Description: Create a framework for simulating physical systems using differential equations and numerical integration methods.
Requirements:
- Numerical Integrators: Implement Euler, RK2, and RK4 methods
- Differential Equations: Solve ordinary differential equations (ODEs)
- Physical Systems: Implement models (spring-mass, pendulum, orbits, populations)
- Visualization: ASCII-based or file-based output of simulation results
- Validation: Verify against known solutions
- Performance: Optimize for long simulations
- Extensibility: Easy to add new systems
Solution Outline
Implement:
- Integrator interface with multiple implementations
- Physical system abstractions
- Simulation runner and output management
- Example systems (N-body, predator-prey, chemical reactions)
- Validation tests against analytical solutions
Exercise 4: Matrix Computation Library
Learning Objectives: Implement linear algebra operations for matrix-based computations.
Real-World Context: Matrix operations are fundamental in machine learning, computer graphics, physics simulations, and scientific computing. Libraries like NumPy and TensorFlow heavily use optimized matrix operations.
Difficulty: Intermediate | Time Estimate: 3-4 hours
Description: Build a comprehensive matrix computation library with various operations and decompositions.
Requirements:
- Basic Operations: Addition, subtraction, multiplication, transposition
- Advanced Operations: Determinant, inverse, rank, trace
- Decompositions: LU decomposition, QR decomposition, SVD
- Eigenvalue Problems: Power method, QR algorithm for eigenvalues
- System Solving: Solve linear systems using Gaussian elimination
- Vector Operations: Dot product, cross product, norms
- Performance: Optimize for large matrices
- Accuracy: Numerical stability for ill-conditioned matrices
Solution Outline
Create:
- Matrix type with efficient storage
- Basic operation implementations
- Decomposition algorithms
- Solver methods
- Benchmark suite for performance testing
Exercise 5: Scientific Visualization and Plotting
Learning Objectives: Create tools for visualizing scientific data and simulation results.
Real-World Context: Data visualization is critical for communicating results to stakeholders and identifying patterns in data. Tools like Matplotlib and Plotly are essential in scientific and data science workflows.
Difficulty: Intermediate | Time Estimate: 2-3 hours
Description: Implement functions to generate ASCII plots, statistical charts, and save visualization data for external plotting tools.
Requirements:
- Line Graphs: Plot 2D line data with axis labels and legends
- Scatter Plots: Visualize point distributions
- Histograms: Show data distributions with ASCII bars
- Box Plots: Display quartile information
- Heatmaps: ASCII-based heat visualizations
- File Output: Generate data in formats compatible with external tools (Gnuplot, CSV)
- Customization: Configurable colors, sizes, and labels
- Statistics Overlay: Add trend lines and statistical measures
Solution Outline
Implement:
- Graph interface with multiple implementations
- Data point and series management
- ASCII rendering engine
- File format exporters (SVG, CSV, Gnuplot)
- Example plots for different data types
Further Reading
- Go math package
- Go math/big package
- Gonum numerical computing library
- Numerical Recipes - Classic numerical algorithms book
- IEEE 754 Floating Point Standard
Practice Exercises
This article provides the mathematical foundation for building sophisticated analytical applications in Go. The exercises guide you through implementing real-world financial and scientific algorithms that are essential in quantitative finance, risk management, data science, and engineering applications.
The next step is to practice these concepts by building increasingly complex mathematical and statistical applications that demonstrate proper numerical computing techniques and optimization strategies.
Summary
Key Takeaways
- Mathematical Precision: Understanding floating-point limitations and numerical stability
- Statistical Analysis: Calculating descriptive statistics and correlation
- Performance Optimization: Using memoization, lookup tables, and parallelization
- Scientific Computing: Implementing simulations and numerical methods
- Complex Numbers: Essential for signal processing and engineering applications
- Algorithm Selection: Choosing the right algorithm for specific problems
- Error Handling: Managing numerical errors and edge cases
Best Practices
- Numerical Stability: Use appropriate algorithms for ill-conditioned problems
- Performance: Profile and optimize computationally intensive operations
- Precision: Choose appropriate floating-point precision for your use case
- Testing: Verify mathematical implementations with known test cases
- Documentation: Document mathematical algorithms and their limitations
- Validation: Compare results with trusted implementations
- Error Bounds: Understand and communicate numerical error bounds
When to Use What
mathpackage: Basic mathematical functions and constantsmath/big: Arbitrary-precision arithmetic for financial or cryptographic applicationsmath/cmplx: Complex number operations for signal processing and engineering- Third-party libraries: Gonum for advanced scientific computing and statistics
- Monte Carlo methods: Complex integrals, option pricing, risk analysis
- Numerical optimization: Parameter fitting, machine learning, control systems
Mathematical and scientific computing transforms your Go applications from simple data processors into powerful analytical tools that can solve complex real-world problems in finance, science, engineering, and data science.