c# - 直接解析子串为double

标签 c# .net f#

如果我有一个字符串,如 1 2 3 并且我确定了一个包含 double 的子字符串的位置,我如何直接从子字符串解析它而不创建临时字符串?

例如,我可以执行 System.Double.Parse(str.Substring(0, 1)) 但这会创建一个缓慢且不必要的临时字符串。是否可以直接从原始字符串的一部分解析一个 double?

编辑

Eric Lippert 在这里质疑我的动机,说“小字符串很便宜”。这样做的动机来自于我对 int 的解析做了同样的事情并看到了巨大的性能改进,因为显然,小字符串并不那么便宜。

这是一个通过临时字符串对整数序列进行词法分析的函数:

let lex f (s: string) =
  let rec inside i0 (s: string, i) =
    if i = s.Length then
      f (s.Substring(i0, i-i0) |> System.Int32.Parse)
    else
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside i0 (s, i+1)
      else
        f (s.Substring(i0, i-i0) |> System.Int32.Parse)
        outside (s, i)
  and outside (s: string, i) =
    if i < s.Length then
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside i (s, i)
      else
        outside (s, i+1)
  outside (s, 0)

从一个字符串中提取 15,625,000 个整数需要 2.4 秒。

这是一个避免临时字符串的版本:

let lex f (s: string) =
  let rec inside n (s: string, i) =
    if i = s.Length then f n else
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside (10*n + int c - int '0') (s, i+1)
      else
        f n
        outside (s, i)
  and outside (s: string, i) =
    if i < s.Length then
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside 0 (s, i)
      else
        outside (s, i+1)
  outside (s, 0)

这需要 0.255 秒,比使用临时字符串的解决方案快 9 倍多!

我看不出为什么 lexing floats 应该有任何不同。因此,通过不提供从子字符串解析 float 的能力,.NET 将性能提升一个数量级。我做了很多科学计算,经常需要分析大量数据,尤其是在启动时,所以我真的不想像这样把性能抛在脑后。

最佳答案

是的,我认为这是完全可行的。您可以编写自己的函数来进行解析,甚至可以将其基于 actual Double.Parse() 的源代码。这段代码看起来并不大也不可怕,我认为您可以根据自己的需要进一步优化它。

关于c# - 直接解析子串为double,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34646404/

相关文章:

c# - 如何从 C# 中的 FTP 请求获取 IP 地址

c# - 开头带有一些无效数据的 TripleDes 解密

function - 如何在 F# 中定义相互依赖的函数?

.net - 多个 .NET 进程的严格负载平衡

f# - Seq.groupBy 是否保留组内的顺序?

c# - 将数据添加到通用字符串数组 C#

c# - 用于多个游标行为的 SetSystemCursor()

c# - 你能在可移植类库中使用数据集和数据表吗

c# - WPF:SizeToContent ="WidthAndHeight"+ WindowState ="Minimized"错误

c# - 如何在 .NET 中创建非 OwnerDraw 按钮?