You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#高效处理含大量数字的大字符串:低内存实现方案问询

无额外内存分配的字符串数字解析方案

针对你遇到的大量数字字符串解析内存/CPU占用过高的问题,核心优化点是避免字符串拆分和子串复制,直接在原字符串内存区域完成解析。下面提供两种高效实现:

方案一:使用ReadOnlySpan(安全无unsafe)

利用.NET的ReadOnlySpan<char>直接切片原字符串,无需分配新内存,同时调用double.TryParse的Span重载完成解析。

public static IEnumerable<double> ParseNumbers(string input)
{
    int numStartIndex = -1;
    for (int i = 0; i < input.Length; i++)
    {
        char c = input[i];
        // 判断当前字符是否属于数字段(数字、小数点,或开头的正负号)
        bool isPartOfNumber = char.IsDigit(c) 
                             || c == '.' 
                             || (numStartIndex == -1 && (c == '+' || c == '-'));

        if (isPartOfNumber)
        {
            if (numStartIndex == -1)
                numStartIndex = i;
        }
        else if (numStartIndex != -1)
        {
            // 提取数字段Span并解析
            var numSpan = new ReadOnlySpan<char>(input, numStartIndex, i - numStartIndex);
            if (double.TryParse(numSpan, out double result))
                yield return result;
            numStartIndex = -1;
        }
    }

    // 处理字符串末尾的数字段
    if (numStartIndex != -1)
    {
        var numSpan = new ReadOnlySpan<char>(input, numStartIndex, input.Length - numStartIndex);
        if (double.TryParse(numSpan, out double result))
            yield return result;
    }
}

优势

  • 完全避免Substring的内存分配,Span仅指向原字符串的内存区域,无数据复制
  • 代码安全易维护,无需开启unsafe编译选项
  • 性能接近unsafe实现,满足绝大多数高吞吐量场景需求

方案二:Unsafe指针解析(极致性能)

如果追求最极致的性能,可以直接操作字符串的char指针,彻底消除任何托管内存开销。需要在项目中开启允许unsafe代码编译选项。

public static unsafe IEnumerable<double> ParseNumbersUnsafe(string input)
{
    fixed (char* inputPtr = input)
    {
        char* currentPtr = inputPtr;
        char* endPtr = inputPtr + input.Length;
        char* numStartPtr = null;

        while (currentPtr < endPtr)
        {
            char c = *currentPtr;
            bool isPartOfNumber = char.IsDigit(c) 
                                 || c == '.' 
                                 || (numStartPtr == null && (c == '+' || c == '-'));

            if (isPartOfNumber)
            {
                if (numStartPtr == null)
                    numStartPtr = currentPtr;
            }
            else if (numStartPtr != null)
            {
                int numLength = (int)(currentPtr - numStartPtr);
                if (double.TryParse(numStartPtr, numLength, null, out double result))
                    yield return result;
                numStartPtr = null;
            }
            currentPtr++;
        }

        // 处理末尾的数字段
        if (numStartPtr != null)
        {
            int numLength = (int)(endPtr - numStartPtr);
            if (double.TryParse(numStartPtr, numLength, null, out double result))
                yield return result;
        }
    }
}

优势

  • 零托管内存分配,直接操作原生指针,性能达到极致
  • 适合超大规模数据解析场景,能显著降低CPU和内存占用

注意事项

  1. 正负号处理:仅允许正负号出现在数字段的开头,避免误解析中间的符号
  2. 无效数字兼容:double.TryParse会自动过滤包含多个小数点等无效格式的数字,返回false
  3. 格式扩展:如果需要支持千分位、特定文化格式,可以传入NumberFormatInfo参数到TryParse中
  4. 空字符串/纯分隔符:代码会自动忽略空的数字段,不会抛出异常

内容的提问来源于stack exchange,提问作者R. Hoek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 16:00:15