如何在Golang中编写isNumeric函数?

时间:2017-08-15 03:40:42

标签: go

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

例如:

  • for row in data: Year,busnum,busname,scaled_power,tla,Location,Yearlink,From,To,Max,Min = row[0:11] if Yearlink==year and Location==location: for From,To,Max,Min in data: From=int(From) To=int(To) Max=float(Max) Min=float(Min) print('From Bus #: %d\t' % From ,'To Bus #: %d\t'% To,'VMAX: %d pu\t' % Max, 'VMIN: %d pu\t' % Min) else: exit 应该返回"abcd123"
  • false"1.4"应返回"240"

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

6 个答案:

答案 0 :(得分:6)

  

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

嗯,这肯定是 正确的方式。

但是,您不需要使用ParseInt。 ParseFloat将完成这项工作。

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

请在此处查看示例:https://play.golang.org/p/D53HRS-KIL

答案 1 :(得分:2)

如果您需要将字符串转换为浮点数strconv.ParseFloat是第一选择 在这里,您只需要知道字符串中只有"0123456789"和最多'.'个{}对我来说isNumDot12xisNumeric,请参阅:
考虑这个(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
}

这个(21.7秒 - 做更多的额外工作“将字符串转换为浮点数”):

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

试一试:

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

输出:

true
false
false
false
1.7822s
false
21.723s
false

答案 2 :(得分:1)

您可以使用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.
*/

您可以在Go Playground上查看。

答案 3 :(得分:1)

所有答案都有效,但尚未提出另一个选项:

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

Playground demo

答案 4 :(得分:0)

我试图评论Adrian的答案,但我想我的声誉得分不足。基于他出色的反应,这是使用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来完成,但是还需要做更多的工作,也许还需要另一种方法。

答案 5 :(得分:0)

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

BenchmarkNumDot-4:657966132:18.2 ns/op
BenchmarkNumeric-4:49575919:226 ns/op
基准Regexp-4:18817201:628 ns/op

代码如下,因为 Playground 不支持基准测试。

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