如何在Golang中编写isNumeric函数?

如何在Golang中编写isNumeric函数?,go,Go,我想检查字符串是否是数字 例如: “abcd123”应返回false “1.4”或“240”应返回true 我考虑过使用ParseInt和ParseFloat(来自strconv包),但不确定这是否正确。您可以使用strconv.Atoi函数检查整数值,使用strconv.ParseFloat检查浮点值。以下是一个例子: package main import ( "fmt" "strconv" ) func main() { v1 := "14" if

我想检查字符串是否是数字

例如:

  • “abcd123”
    应返回
    false
  • “1.4”或
    “240”
    应返回
    true

我考虑过使用
ParseInt
ParseFloat
(来自
strconv
包),但不确定这是否正确。

您可以使用
strconv.Atoi
函数检查整数值,使用
strconv.ParseFloat
检查浮点值。以下是一个例子:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    v1 := "14"

    if _, err := strconv.Atoi(v1); err == nil {
        fmt.Printf("%q looks like a number.\n", v1)
    } else {
        fmt.Printf("%q is not a number.\n", v1)
    }

    v2 := "1.4"
    if _, err := strconv.ParseFloat(v2, 64); err == nil {
        fmt.Printf("%q looks like a float.\n", v2)
    } else {
        fmt.Printf("%q is not a float.\n", v2)
    }
}

/* Output:
"14" looks like a number.
"1.4" looks like a float.
*/
你可以在网上查一下

我正在考虑使用strconv ParseInt和ParseFloat,但不确定 如果这是正确的方法

嗯,这的确是一条正确的道路

不过,您不需要使用ParseInt。我来做这项工作

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

请参见此处的示例:

如果需要将字符串转换为浮点数
strconv。ParseFloat
是首选。
这里您只需要知道字符串中只有一个
“0123456789”
,最大一个
对于我来说,这里的
isNumDot
isNumeric
快12x
,请参见:
考虑这个(1.7秒)-优化性能:

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
}

试试看:

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)
}

使用基准测试(
isNumDot
isNumeric
更快):

基准:

package main

import (
    "testing"
)

var r bool

func BenchmarkIsNumDot(b *testing.B) {
    for i := 0; i < b.N; i++ {
        r = isNumDot("a 240") || isNumDot("abcd123") || isNumDot("0.4.") || isNumDot("240 ")
    }
}

func BenchmarkIsNumeric(b *testing.B) {
    for i := 0; i < b.N; i++ {
        r = isNumeric("a 240") || isNumeric("abcd123") || isNumeric("0.4.") || isNumeric("240 ")
    }
}
主程序包
进口(
“测试”
)
瓦尔布尔
func BenchmarkIsNumDot(b*testing.b){
对于i:=0;i
所有答案都有效,但还有一个选项尚未建议:

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

我试图对阿德里安的回答发表评论,但我想我没有足够的声望。基于他的出色反应,这里是一个使用PCRE的变体。如果您不熟悉正则表达式,请简要说明符号:

“^”匹配输入的开头(即字符串的开头)

“$”匹配输入的结尾(即字符串的结尾)

“()”是分组运算符

“*”与0或更多项匹配

“+”匹配1个或多个

“?”正好匹配0或1

“\d”是一个字符类,表示字符值0到9

因此,下面的代码至少需要一个前导0,允许使用“0”,以及通常标识为浮点值的所有内容。你可以尝试一下

func isFloat(s string) bool {
    return regexp.MatchString(`^\d+(\.\d*)?$`, s)
}
当然,如果您调用此函数来验证数据,则应清除该函数:

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

这只适用于ASCII字符。如果您正在处理UTF8或另一个多字节字符集(MBCS),可以使用regexp来完成,但还需要做更多的工作,也许还需要另一种方法。

我今天在一个高通量系统中遇到了这个问题,并对这三个建议进行了基准测试。结果:

基准NUMDOT-4:657966132:18.2 ns/op
基准数字-4:49575919:226 ns/op
基准regexp-4:18817201:628 ns/op

由于操场不支持基准测试,因此代码如下

package main

import (
    "regexp"
    "strconv"
    "testing"
)


func BenchmarkNumDot(b *testing.B) {
    for i := 0; i < b.N; i++ {
        isNumDot("abc")
    isNumDot("123")
    isNumDot("12.34")
    isNumDot("1.2.3.4")
    }
}

func BenchmarkNumeric(b *testing.B) {
    for i := 0; i < b.N; i++ {
        isNumeric("abc")
    isNumeric("123")
    isNumeric("12.34")
    isNumeric("1.2.3.4")
    }
}

func BenchmarkRegexp(b *testing.B) {
    re := regexp.MustCompile(`^[0-9]+(\.[0-9]+)?$`)

    for i := 0; i < b.N; i++ {
        isNumReg("abc", re)
        isNumReg("123", re)
        isNumReg("12.34", re)
        isNumReg("1.2.3.4", re)
    }
}

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 isNumReg(s string, re *regexp.Regexp) bool {
    return re.Match([]byte(s))
}
主程序包
进口(
“regexp”
“strconv”
“测试”
)
func BenchmarkNumDot(b*testing.b){
对于i:=0;i9'{
返回错误
}
}
返回真值
}
func是数字(s字符串)布尔{
_,err:=strconv.ParseFloat(s,64)
返回err==nil
}
func isNumReg(s字符串,re*regexp.regexp)bool{
返回重新匹配([]字节))
}

您可以像您所说的那样使用ParseInt/ParseFloat来完成这项工作,或者您可以编写一个非常简单的正则表达式来完成这项工作。同样值得考虑的是,
strconv.ParseFloat
将允许使用科学符号,这对于您的情况可能是不可取的:如果您对某些东西进行基准测试,请使用@TehSphinX,谢谢您的评论,这里对我来说很明显,
isNumDot
isNumeric
快,因为
strconv.ParseFloat
做更多额外的工作“将字符串转换为浮点数”。
func isFloat(s string) bool {
    return regexp.MatchString(`^\d+(\.\d*)?$`, s)
}
str := strings.TrimSpace(someString)
if isFloat(str) {
  ...
}
package main

import (
    "regexp"
    "strconv"
    "testing"
)


func BenchmarkNumDot(b *testing.B) {
    for i := 0; i < b.N; i++ {
        isNumDot("abc")
    isNumDot("123")
    isNumDot("12.34")
    isNumDot("1.2.3.4")
    }
}

func BenchmarkNumeric(b *testing.B) {
    for i := 0; i < b.N; i++ {
        isNumeric("abc")
    isNumeric("123")
    isNumeric("12.34")
    isNumeric("1.2.3.4")
    }
}

func BenchmarkRegexp(b *testing.B) {
    re := regexp.MustCompile(`^[0-9]+(\.[0-9]+)?$`)

    for i := 0; i < b.N; i++ {
        isNumReg("abc", re)
        isNumReg("123", re)
        isNumReg("12.34", re)
        isNumReg("1.2.3.4", re)
    }
}

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 isNumReg(s string, re *regexp.Regexp) bool {
    return re.Match([]byte(s))
}