douzhongjiu2263 2017-08-15 03:40
浏览 256
已采纳

如何在Golang中编写isNumeric函数?

I want to check if a string is numeric.

For example:

  • "abcd123" should return false.
  • "1.4" or "240" should return true.

I thought about using ParseInt and ParseFloat (from the strconv package), but am not sure if that is the right way.

  • 写回答

5条回答 默认 最新

  • doushe8577 2017-08-15 04:21
    关注

    I was thinking of using strconv ParseInt and ParseFloat but not sure if that is the right way.

    Well, it's certainly a right way.

    You don't need to use ParseInt, though. ParseFloat will do the job.

    func isNumeric(s string) bool {
        _, err := strconv.ParseFloat(s, 64)
        return err == nil
    }
    

    See an example here: https://play.golang.org/p/D53HRS-KIL

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • dtbsezxw28056 2017-08-15 03:58
    关注

    You can use the strconv.Atoi function for check integer values, and the strconv.ParseFloat for float values. Below is an example:

    package main
    
    import (
        "fmt"
        "strconv"
    )
    
    func main() {
        v1 := "14"
    
        if _, err := strconv.Atoi(v1); err == nil {
            fmt.Printf("%q looks like a number.
    ", v1)
        } else {
            fmt.Printf("%q is not a number.
    ", v1)
        }
    
        v2 := "1.4"
        if _, err := strconv.ParseFloat(v2, 64); err == nil {
            fmt.Printf("%q looks like a float.
    ", v2)
        } else {
            fmt.Printf("%q is not a float.
    ", v2)
        }
    }
    
    /* Output:
    "14" looks like a number.
    "1.4" looks like a float.
    */
    

    You can check it on the Go Playground.

    评论
  • dqqxkq4047 2017-08-15 07:15
    关注

    If you need to convert the string to a floating-point number strconv.ParseFloat is the first choice.
    Here you just need to know that there is only "0123456789" and maximum one '.' in your string, here for me isNumDot is 12x faster than isNumeric, see:
    Consider this (1.7 seconds) - optimized for performance:

    func isNumDot(s string) bool {
        dotFound := false
        for _, v := range s {
            if v == '.' {
                if dotFound {
                    return false
                }
                dotFound = true
            } else if v < '0' || v > '9' {
                return false
            }
        }
        return true
    }
    

    and this (21.7 seconds - doing more extra works "converts the string to a floating-point number"):

    func isNumeric(s string) bool {
        _, err := strconv.ParseFloat(s, 64)
        return err == nil
    }
    

    try it:

    package main
    
    import (
        "fmt"
        "strconv"
        "time"
    )
    
    func isNumDot(s string) bool {
        dotFound := false
        for _, v := range s {
            if v == '.' {
                if dotFound {
                    return false
                }
                dotFound = true
            } else if v < '0' || v > '9' {
                return false
            }
        }
        return true
    }
    
    func isNumeric(s string) bool {
        _, err := strconv.ParseFloat(s, 64)
        return err == nil
    }
    
    func main() {
        fmt.Println(isNumDot("240"))     //true
        fmt.Println(isNumDot("abcd123")) //false
        fmt.Println(isNumDot("0.4."))    //false
        fmt.Println(isNumDot("240 "))    //false
        benchmark(isNumDot)
        benchmark(isNumeric)
    }
    
    func benchmark(f func(string) bool) {
        var res bool
        t := time.Now()
        for i := 0; i < 100000000; i++ {
            res = f("a 240") || f("abcd123") || f("0.4.") || f("240 ")
        }
        fmt.Println(time.Since(t))
        fmt.Println(res)
    }
    

    output:

    true
    false
    false
    false
    1.7822s
    false
    21.723s
    false
    
    评论
  • douke1891 2017-08-15 13:52
    关注

    All the answers are valid, but there's another option not yet suggested:

    re := regexp.MustCompile(`^[0-9]+(\.[0-9]+)?$`)
    isNum := re.Match([]byte("ab123"))
    

    Playground demo

    评论
  • douchun5976 2019-04-10 04:34
    关注

    I tried to comment on Adrian's answer but I guess I don't have enough reputation points. Building on his excellent response, here is a variation using PCRE. Some brief explanation on the symbols if you are unfamiliar with regular expressions:

    "^" matches the start of input (i.e. beginning of your string)

    "$" matches the end of input (i.e. the end of your string)

    "()" are grouping operators

    "*" matches 0 or more

    "+" matches 1 or more

    "?" matches exactly 0 or 1

    "\d" is a character class which represents the character values 0 through 9

    So, the following would require at least a leading 0, permit "0.", and everything else that is normally identified as a floating point value. You can experiment with this a bit.

    func isFloat(s string) bool {
        return regexp.MatchString(`^\d+(\.\d*)?$`, s)
    }
    

    Naturally, if you are calling this function to validate data, it should be cleaned:

    str := strings.TrimSpace(someString)
    if isFloat(str) {
      ...
    }
    

    That only works on ASCII characters. If you are dealing with UTF8 or another multi-byte character set (MBCS), it can be done with regexp but more work would be required and perhaps another approach altogether.

    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥15 matlab+波形匹配算法
  • ¥15 转录组分析做聚类树图时癌旁组被分到了癌组
  • ¥15 大一Python字典
  • ¥15 multisim电路设计(相关搜索:设计报告)
  • ¥15 从github上下载的项目到ecplise上咋运行
  • ¥15 PC-lint Plus
  • ¥15 gpl24676注释
  • ¥15 php5.3内存泄露
  • ¥15 DigSilent如何复制复合模型到自己案例?
  • ¥15 求日版华为b610s-77a 官方公版固件,有偿