【问题标题】:How to check if a string is numeric Julia如何检查字符串是否为数字 Julia
【发布时间】:2019-06-12 08:42:38
【问题描述】:

一直在互联网上搜索试图解决这个问题。试过isnumeric,但这只适用于AbstractChar。如果可能的话,我宁愿不必使用tryparse,但如果这是唯一的解决方案,那就这样吧……如果是,为什么还没有实现检查字符串是否为数字的功能?

【问题讨论】:

  • 为什么不tryparse
  • tryparse 是正确的朱莉娅。没有任何可能的实现不涉及尝试将字符串解析为数字。
  • “数字”是什么意思? 1.0e2 是数字吗? 6.2f22 是数字吗? 0x02 呢?还是0b100101?还是0xdead_beef.cap23
  • @DNF 因为对我个人来说,这感觉有点像黑客攻击。
  • @MattB。我只是指整数,但理论上是在寻找一种检查任何数值的方法

标签: string numbers julia numeric


【解决方案1】:

我发现最快的解决方案是按照推荐使用tryparse

function check_str2(a)
    return tryparse(Float64, a) !== nothing
end

平均为 20ns,而正则表达式为 40ns。

如果不进行转换,就无法检查字符串是否作为 int 有效,主要原因是在性能很重要的地方并没有很多令人信服的用例。在大多数地方,您想知道是否可以将某些内容解析为数字以将其用作数字,并且在极少数情况下,额外的一对 ns 可能无关紧要。

【讨论】:

  • 我使用了来自 benchmarktools 的@benchmark。我在 Julia 1.1.1
  • 但是,您的解决方案不起作用check_str2("60.0xxx") 返回true60.0xxx 不是数字。 Parsers.tryparse 的问题可能是它试图从String 中提取一个数字,并且在它刚刚开始时它很高兴。
  • ^ 据我的测试可以看出,以上是错误的
  • 在任何最近的 Julia 上(即 1.0 版之后),check_str2("60.0xxx") returns false. 我很惊讶它竟然返回了true。)
  • 实际上Parsers.tryparse(来自Parsers.jl 包)确实具有@PrzemyslawSzufel 指示的行为。但是,Julia Base 中的 tryparse 没有相同的行为(即它可以工作),实际上比下面的 check_str 更快。我编辑了这个解决方案以使用Base 版本。
【解决方案2】:

您通常使用正则表达式来检查字符串是否为数字:

julia> re = r"^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$";

julia> occursin(re,"123.")
true

julia> occursin(re,"123.0")
true

julia> occursin(re,"123.012")
true

julia> occursin(re,"123")
true 

julia> occursin(re,"ab")
false

julia> occursin(re,"ab123.1")
false

julia> occursin(re,"123.1e")
false

注意:我使用了Regular expression for floating point numbers找到的正则表达式,如果你只是想要整数部分或包含指数,那么现成的正则表达式也很容易找到。

编辑:基准测试。

让我们考虑以下函数来检查字符串是否为数字:

function check_str(a)
    try
        parse(Float64,a)
        true
    catch
        false
    end
end

这里是基准测试。请注意,正则表达式大约快 200 倍(如果我们决定同时查找指数部分,则增加会更小)并且不会分配。

julia> using BenchmarkTools

julia> @btime check_str("60.0a")
  15.359 μs (18 allocations: 816 bytes)
false

julia> @btime occursin($re,"60.0a")
  67.023 ns (0 allocations: 0 bytes)
false

String解析成功后速度差距小很多:

julia> @btime check_str("60.0")
  298.833 ns (0 allocations: 0 bytes)
true

julia> @btime occursin($re,"60.0")
  58.865 ns (0 allocations: 0 bytes)
true

【讨论】:

  • tryparse相比有什么优势吗?
  • 大约快 200 倍,代码更短且不分配。我会用一个例子来更新我的答案。
  • 如果你使用 tryparse 而不是从 parse 中捕获异常,平均只有 20ns(相比 regex 的 30ns)
  • 惊人的工作@PrzemyslawSzufel !不过,我会记住奥斯卡史密斯关于时间的评论。目前我的问题不需要超级核心优化,所以无论哪种方式都应该没问题。尽管这个答案绝对令人惊叹并且付出了很多努力,但 Oscar Smith 的答案更实用,因为它还考虑了十六进制和科学记数法,就像 Matt B 指出的那样。
  • Oscar 的回答不起作用(请参阅我下面的评论) - 它可能会为 Strings 返回误报,例如 ``"60xxx"` 或 60.0xxx。您应该使用Base.parse(比正则表达式慢)或正则表达式。
【解决方案3】:

这对我有用:

isa(tryparse(Float64,"StringNumber"), Number)    # true | false

【讨论】:

    【解决方案4】:

    正如 OP 在 cmets 中建议他们只需要检查整数,您仍然可以使用 isnumeric(或者最好使用 isdigit):

    isintstring(str) = all(isdigit(c) for c in str)
    

    这似乎比这里的其他答案更快。在我的机器上,这个基准大约是 37/38 ns,而 tryparse 解决方案的基准大约是 64/65 ns。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-28
      • 2011-11-27
      • 2012-12-21
      • 2011-07-22
      相关资源
      最近更新 更多