-
Notifications
You must be signed in to change notification settings - Fork 0
/
math.go
194 lines (170 loc) · 4.08 KB
/
math.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package util
import (
"fmt"
"math"
"regexp"
"strconv"
)
// unit代表小數點後取到第幾位
func Round(num, unit float64) float64 {
return math.Round(num*math.Pow(10, unit)) / math.Pow(10, unit)
}
// 找平均值
func Average(data []float64) (avg float64) {
sum := 0.0
for i := range data {
sum += data[i]
}
avg = sum / float64(len(data))
return
}
// 找標準差,會順便一起算平均值
func Standard(data []float64) (SD, avg float64) {
avg = Average(data)
sigma := 0.0
for i := range data {
sigma += math.Pow((data[i] - avg), 2)
}
Variance := sigma / float64(len(data))
SD = math.Sqrt(Variance)
return
}
// 找極值
func FindExtremum(data []float64) (max, min float64) {
if len(data) == 0 {
return
}
max = data[0]
min = data[0]
for _, item := range data {
if item > max {
max = item
}
if item < min {
min = item
}
}
return
}
// 字串計算(字串+數字、字串+字串)(減法有問題)
// 輸出會依照stringNum的位元數來輸出,多出來的就不輸出
// 字串計算(字串+數字、字串+字串)
// 輸出會依照stringNum的位元數來輸出,多出來的就不輸出
func StringCalculate(stringNum string, inputNum any) (outputNum string) {
fmt.Printf("stringNum: %v, inputNum: %v\n", stringNum, inputNum)
num := 0
// 用於字串變數字
switch temp := inputNum.(type) {
case string:
num, _ = strconv.Atoi(temp)
case int:
num = temp
}
carry := num
for i := len(stringNum) - 1; i >= 0; i-- {
// 數字加進位,加完後進位要清空(第一次的carry就是要加的數字)
digitNum, _ := strconv.Atoi(string(stringNum[i]))
if carry < 0 {
digitNum += (carry % 10)
carry /= 10
} else {
digitNum += carry
carry = 0
}
// 超過9要進位
if digitNum > 9 {
carry = (digitNum) / 10
digitNum = (digitNum) % 10
}
// 小於0要退位(-的num)
if digitNum < 0 {
digitNum = 10 + digitNum
carry += -1
}
// 由右到左拼起來
outputNum = fmt.Sprint(digitNum) + outputNum
}
return
}
// 自動計算系統維護之ID(加法或減法都可以)
// 沒有輸入prefix會以serialStr前面的prefix為主
// 沒有輸入initNumStr會自動找編號位元大小,有的話會以initNumStr位元大小為主
func AddSerial(prefix, initNumStr, serialStr string, addend int) (output string) {
if serialStr == "" {
output = initNumStr
if prefix != "" {
output = prefix + output
}
return
}
// 數字檢查regexp
numRegexp := regexp.MustCompile("[0-9]")
carry := 0
for i := len(serialStr) - 1; i >= 0; i-- {
// 如果不是數字就把前面的文字加上然後回傳
if !numRegexp.MatchString(string(serialStr[i])) {
if prefix != "" {
output = prefix + output
return
}
output = serialStr[:i+1] + output
return
}
// A的該位數加上B的該位數再加進位
digitNum, _ := strconv.Atoi(string(serialStr[i]))
digitNum = digitNum + (addend % 10) + carry
// 超過9要進位
if digitNum > 9 {
carry = (digitNum) / 10
digitNum = (digitNum) % 10
}
// 小於0要退位
if digitNum < 0 {
carry = -1
digitNum = 10 + digitNum
}
// 每次只拿個位數計算
addend /= 10
// 由右到左拼起來
output = fmt.Sprint(digitNum) + output
// 如果輸出長度已經等於initNumStr的長度就把前面的文字加上然後回傳
if len(serialStr)-i == len(initNumStr) {
if prefix != "" {
output = prefix + output
}
return
}
}
return
}
// 累加各種型別的數字
func Calculate[T int | int64 | float64](nums ...any) (outNum T) {
totalNum := 0.0
for _, num := range nums {
fmt.Printf("num: %T, %v\n", num, num)
switch tempNum := num.(type) {
case string:
convertNum, err := strconv.ParseFloat(tempNum, 64)
if err != nil {
continue
}
totalNum += convertNum
case int:
totalNum += float64(tempNum)
case int8:
totalNum += float64(tempNum)
case int16:
totalNum += float64(tempNum)
case int32:
totalNum += float64(tempNum)
case int64:
totalNum += float64(tempNum)
case float32:
totalNum += float64(tempNum)
case float64:
totalNum += tempNum
}
}
outNum = T(totalNum)
return
}