如果我有一个字符串,如 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/