github.com/avicd/go-utilx@v0.1.0/conv/number.go (about) 1 package conv 2 3 import ( 4 "math" 5 "strings" 6 "unicode" 7 ) 8 9 type numInfo struct { 10 negative bool 11 base int 12 integer string 13 decimal string 14 } 15 16 func isNumChar(r rune, base int) bool { 17 if base <= 10 { 18 return r >= '0' && r < '0'+rune(base) 19 } else { 20 return unicode.IsNumber(r) || r >= 'a' && r < 'a'+rune(base-10) 21 } 22 } 23 24 func parseNum(num string) *numInfo { 25 buf := strings.ToLower(num) 26 info := &numInfo{} 27 var cut int 28 if cut = strings.Index(buf, "+"); cut > -1 { 29 buf = buf[cut+1:] 30 } 31 if cut = strings.Index(buf, "-"); cut > -1 { 32 buf = buf[cut+1:] 33 info.negative = true 34 } 35 base := 10 36 tokens := map[string]int{"0b": 2, "0o": 8, "0x": 16} 37 for tk, bs := range tokens { 38 if cut = strings.Index(buf, tk); cut > -1 { 39 base = bs 40 buf = buf[cut+len(tk):] 41 break 42 } 43 } 44 info.base = base 45 valid := func(r rune) bool { 46 return isNumChar(r, base) 47 } 48 invalid := func(r rune) bool { 49 return !isNumChar(r, base) 50 } 51 if cut = strings.IndexFunc(buf, valid); cut > -1 { 52 buf = buf[cut:] 53 } 54 if cut = strings.IndexFunc(buf, invalid); cut > -1 { 55 info.integer = buf[:cut] 56 buf = buf[cut:] 57 if buf[0] == '.' { 58 buf = buf[1:] 59 if cut = strings.IndexFunc(buf, valid); cut > -1 { 60 if cut = strings.IndexFunc(buf, invalid); cut > -1 { 61 info.decimal = buf[:cut] 62 } else { 63 info.decimal = buf 64 } 65 } 66 } 67 } else { 68 info.integer = buf 69 } 70 return info 71 } 72 73 func parseDigit(r rune) int32 { 74 if r >= 'a' { 75 return r - 'a' + 10 76 } else if r <= '9' && r >= '0' { 77 return r - '0' 78 } 79 return 0 80 } 81 82 func ParseInt(input string) int64 { 83 info := parseNum(input) 84 high := len(info.integer) 85 var sum int64 = 0 86 var level int64 = 1 87 for _, ch := range info.integer { 88 high-- 89 level = int64(math.Pow(float64(info.base), float64(high))) 90 sum += int64(parseDigit(ch)) * level 91 } 92 if info.negative { 93 sum = -sum 94 } 95 return sum 96 } 97 98 func ParseFloat(input string) float64 { 99 info := parseNum(input) 100 var sum = 0.0 101 high := len(info.integer) 102 plain := info.integer + info.decimal 103 for _, ch := range plain { 104 high-- 105 level := math.Pow(float64(info.base), float64(high)) 106 sum += float64(parseDigit(ch)) * level 107 } 108 if info.negative { 109 sum = -sum 110 } 111 return sum 112 }