gitee.com/quant1x/num@v0.3.2/median.go (about) 1 package num 2 3 import ( 4 "gitee.com/quant1x/num/internal/partial" 5 "math" 6 "slices" 7 ) 8 9 // Median returns median value of series. 10 // Linear interpolation is used for odd length. 11 // 12 // 中间值 13 // TODO:未加验证, 14 func Median[T Number](values []T) DType { 15 if len(values) == 0 { 16 return NaN() 17 } 18 if len(values) == 1 { 19 return DType(0) 20 } 21 22 if len(values)%2 == 0 { 23 i := len(values) / 2 24 return DType(values[i-1]+values[i]) / 2 25 } 26 27 return DType(values[len(values)/2]) 28 } 29 30 func __median_go[T Number](x []T) T { 31 xLen := len(x) 32 if xLen == 0 { 33 return T(0) 34 } 35 if xLen == 1 { 36 return x[0] 37 } 38 if len(x)%2 == 1 { 39 x = slices.Clone(x) 40 i := len(x) / 2 41 partial.TopK(x, i+1) 42 return x[i] 43 } 44 q := float64(0.5) 45 46 return __quantile_go(x, T(q)) 47 } 48 49 func __quantile_go[T Number](x []T, q T) T { 50 xLen := len(x) 51 if xLen == 0 { 52 return T(0) 53 } 54 if xLen == 1 { 55 return x[0] 56 } 57 if q == T(0) { 58 return __go_min(x) 59 } 60 if q == T(1) { 61 return __go_max(x) 62 } 63 x = slices.Clone(x) 64 f := T(len(x)-1) * q 65 i := int(math.Floor(float64(f))) 66 if float64(q) < float64(0.5) { 67 partial.TopK(x, i+2) 68 a := __go_max(x[:i+1]) 69 b := x[i+1] 70 return a + (b-a)*(f-T(i)) 71 } else { 72 partial.TopK(x, i+1) 73 a := x[i] 74 b := __go_min(x[i+1:]) 75 return a + (b-a)*(f-T(i)) 76 } 77 }