From ad5c18667ab6b0ea8363d75aa4c963e18f5a362a Mon Sep 17 00:00:00 2001 From: 兔子 Date: Mon, 21 Dec 2020 17:19:41 +0800 Subject: [PATCH] add mathmatic calc --- files_unix.go | 21 +++ files_windows.go | 19 ++ math.go | 294 ++++++++++++++++++++++++++++++ memory_linux.go => memory_unix.go | 0 4 files changed, 334 insertions(+) create mode 100644 files_unix.go create mode 100644 files_windows.go create mode 100644 math.go rename memory_linux.go => memory_unix.go (100%) diff --git a/files_unix.go b/files_unix.go new file mode 100644 index 0000000..d5a972d --- /dev/null +++ b/files_unix.go @@ -0,0 +1,21 @@ +//+build linux darwin + +package staros + +import ( + "os" + "syscall" + "time" +) + +func timespecToTime(ts syscall.Timespec) time.Time { + return time.Unix(int64(ts.Sec), int64(ts.Nsec)) +} + +func GetFileCreationTime(fileinfo os.FileInfo) time.Time { + return timespecToTime(stat_t.Ctim) +} + +func GetFileAccessTime(fileinfo os.FileInfo) time.Time { + return timespecToTime(stat_t.Atim) +} diff --git a/files_windows.go b/files_windows.go new file mode 100644 index 0000000..8ea3f27 --- /dev/null +++ b/files_windows.go @@ -0,0 +1,19 @@ +// +build windows + +package staros + +import ( + "os" + "syscall" + "time" +) + +func GetFileCreationTime(fileinfo os.FileInfo) time.Time { + d := fileinfo.Sys().(*syscall.Win32FileAttributeData) + return time.Unix(0, d.CreationTime.Nanoseconds()) +} + +func GetFileAccessTime(fileinfo os.FileInfo) time.Time { + d := fileinfo.Sys().(*syscall.Win32FileAttributeData) + return time.Unix(0, d.LastAccessTime.Nanoseconds()) +} diff --git a/math.go b/math.go new file mode 100644 index 0000000..d38bd98 --- /dev/null +++ b/math.go @@ -0,0 +1,294 @@ +package staros + +import ( + "errors" + "fmt" + "math" + "strconv" + "strings" +) + +func Calc(math string) (float64, error) { + math = strings.Replace(math, " ", "", -1) + math = strings.ToLower(math) + if err := check(math); err != nil { + return 0, err + } + return calc(math) +} + +func check(math string) error { + math = strings.Replace(math, " ", "", -1) + math = strings.ToLower(math) + var bracketSum int + var signReady bool + for k, v := range math { + if string([]rune{v}) == "(" { + bracketSum++ + } + if string([]rune{v}) == ")" { + bracketSum-- + } + if bracketSum < 0 { + return fmt.Errorf("err at position %d.Reason is right bracket position not correct,except (", k) + } + if containSign(string([]rune{v})) { + if signReady { + if string([]rune{v}) != "+" && string([]rune{v}) != "-" { + return fmt.Errorf("err at position %d.Reason is sign %s not correct", k, string([]rune{v})) + } + signReady = false + } else { + signReady = true + } + } + } + if bracketSum != 0 { + return fmt.Errorf("Error:right bracket is not equal as left bracket") + } + return nil +} + +func calc(math string) (float64, error) { + var bracketLeft int + var bracketRight int + var DupStart int = -1 + for pos, str := range math { + if string(str) == "(" { + bracketLeft = pos + } + if string(str) == ")" { + bracketRight = pos + break + } + } + if bracketRight == 0 && bracketLeft != 0 || (bracketLeft > bracketRight) { + return 0, fmt.Errorf("Error:bracket not correct at %d ,except )", bracketLeft) + } + if bracketRight == 0 && bracketLeft == 0 { + return calcLong(math) + } + line := math[bracketLeft+1 : bracketRight] + num, err := calcLong(line) + if err != nil { + return 0, err + } + for i := bracketLeft - 1; i >= 0; i-- { + if !containSign(math[i : i+1]) { + DupStart = i + continue + } + break + } + if DupStart != -1 { + sign := math[DupStart:bracketLeft] + num, err := calcDuaFloat(sign, num) + if err != nil { + return 0, err + } + math = math[:DupStart] + fmt.Sprintf("%.15f", num) + math[bracketRight+1:] + DupStart = -1 + } else { + math = math[:bracketLeft] + fmt.Sprintf("%.15f", num) + math[bracketRight+1:] + } + return calc(math) +} + +func calcLong(str string) (float64, error) { + var sigReady bool = false + var sigApply bool = false + var numPool []float64 + var operPool []string + var numStr string + var oper string + if str[0:1] == "+" || str[0:1] == "-" { + sigReady = true + } + for _, stp := range str { + if sigReady && containSign(string(stp)) { + sigReady = false + sigApply = true + oper = string(stp) + continue + } + if !containSign(string(stp)) { + sigReady = false + numStr = string(append([]rune(numStr), stp)) + continue + } + if !sigReady { + sigReady = true + } + if sigApply { + num, err := calcDua(oper, numStr) + if err != nil { + return 0, err + } + sigApply = false + numPool = append(numPool, num) + } else { + num, err := parseNumbic(numStr) + if err != nil { + return 0, err + } + numPool = append(numPool, num) + } + numStr = "" + operPool = append(operPool, string(stp)) + } + if sigApply { + num, err := calcDua(oper, numStr) + if err != nil { + return 0, err + } + numPool = append(numPool, num) + } else { + num, err := parseNumbic(numStr) + if err != nil { + return 0, err + } + numPool = append(numPool, num) + } + return calcPool(numPool, operPool) +} + +func calcPool(numPool []float64, operPool []string) (float64, error) { + if len(numPool) == 1 && len(operPool) == 0 { + return numPool[0], nil + } + if len(numPool) < len(operPool) { + return 0, errors.New(("Operate Signal Is too much")) + } + calcFunc := func(k int, v string) (float64, error) { + num, err := calcSigFloat(numPool[k], v, numPool[k+1]) + if err != nil { + return 0, err + } + tmp := append(numPool[:k], num) + numPool = append(tmp, numPool[k+2:]...) + operPool = append(operPool[:k], operPool[k+1:]...) + return calcPool(numPool, operPool) + } + for k, v := range operPool { + if v == "^" { + return calcFunc(k, v) + } + } + for k, v := range operPool { + if v == "*" || v == "/" { + return calcFunc(k, v) + } + } + for k, v := range operPool { + return calcFunc(k, v) + } + return 0, nil +} + +func calcSigFloat(floatA float64, b string, floatC float64) (float64, error) { + switch b { + case "+": + return floatA + floatC, nil + case "-": + return floatA - floatC, nil + case "*": + return floatA * floatC, nil + case "/": + if floatC == 0 { + return 0, errors.New("Divisor cannot be 0") + } + return floatA / floatC, nil + case "^": + return math.Pow(floatA, floatC), nil + } + return 0, fmt.Errorf("unexpect method:%s", b) +} + +func calcSig(a, b, c string) (float64, error) { + floatA, err := parseNumbic(a) + if err != nil { + return 0, err + } + floatC, err := parseNumbic(c) + if err != nil { + return 0, err + } + return calcSigFloat(floatA, b, floatC) +} + +func calcDuaFloat(a string, floatB float64) (float64, error) { + switch a { + case "sin": + return math.Sin(floatB), nil + case "cos": + return math.Cos(floatB), nil + case "tan": + return math.Tan(floatB), nil + case "abs": + return math.Abs(floatB), nil + case "arcsin": + return math.Asin(floatB), nil + case "arccos": + return math.Acos(floatB), nil + case "arctan": + return math.Atan(floatB), nil + case "sqrt": + return math.Sqrt(floatB), nil + case "loge": + return math.Log(floatB), nil + case "log10": + return math.Log10(floatB), nil + case "log2": + return math.Log2(floatB), nil + case "floor": + return math.Floor(floatB), nil + case "ceil": + return math.Ceil(floatB), nil + case "round": + return math.Round(floatB), nil + case "trunc": + return math.Trunc(floatB), nil + case "+": + return 0 + floatB, nil + case "-": + return 0 - floatB, nil + } + return 0, fmt.Errorf("unexpect method:%s", a) +} +func calcDua(a, b string) (float64, error) { + floatB, err := parseNumbic(b) + if err != nil { + return 0, err + } + return calcDuaFloat(a, floatB) +} + +func parseNumbic(str string) (float64, error) { + switch str { + case "pi": + return float64(math.Pi), nil + case "e": + return float64(math.E), nil + default: + return strconv.ParseFloat(str, 64) + } +} + +func containSign(str string) bool { + var sign []string = []string{"+", "-", "*", "/", "^"} + for _, v := range sign { + if str == v { + return true + } + } + return false +} + +func contain(pool []string, str string) bool { + for _, v := range pool { + if v == str { + return true + } + } + return false +} diff --git a/memory_linux.go b/memory_unix.go similarity index 100% rename from memory_linux.go rename to memory_unix.go