如何在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))
}