将字符串整数转换为 int 的任何比 convert.toint32 更有效的方法

本文关键字:toint32 convert 有效 方法 任何比 整数 转换 int 字符串 | 更新日期: 2023-09-27 18:24:57

有没有比在 c# 中使用 Convert.ToInt32() 更有效的方法将字符串整数转换为 int?

我有一个程序可以将很多字符串转换为整数。 这些值以字符串格式从文本文件中读取。

将字符串整数转换为 int 的任何比 convert.toint32 更有效的方法

不,可能不是,至少到目前为止不是。我尝试了这个快速而肮脏的基准测试:

private static int toint(string s) {
    int res = 0;
    foreach (var c in s) {
        res = 10*res + (c - '0');
    }
    return res;
}
static void Main() {
    var s = DateTime.Now;
    for (int i = 0 ; i != 10000000 ; i++) {
        if (Convert.ToInt32("112345678") == 0) break;
    }
    var m = DateTime.Now;
    for (int i = 0; i != 10000000; i++) {
        if (toint("112345678") == 0) break;
    }
    Console.WriteLine("{0} {1}", DateTime.Now-m, m-s);
}

我的toint方法跳过了各种验证,得到的结果在Convert.ToInt32上仅提高了 40%:1.14 秒对 1.86 秒。

只需向脏toint添加基本验证几乎完全消除了它的优势:这种方法

private static int toint(string s) {
    int res = 0;
    foreach (var c in s) {
        if (Char.IsDigit(c))
            res = 10*res + (c - '0');
    }
    return res;
}

运行时间为 1.62 秒,或提高 13%,同时保持根本不正确

使用此方法:

    private static int Parse(string s)
    {
        int value = 0;
        for (var i = 0; i < s.Length; i++)
        {
            value = value*10 + (s[i] - '0');
        }
        return value;
    }

我得到 750 毫秒而不是 18+ 秒int.Parse 100M 转换。

我不会推荐它,除非这是你真正的瓶颈,你不关心任何形式的验证。

如果您正在从 Stream 中读取整数,那么您可以通过避免初始化字符串的开销来进行优化。

例如,假设您的数字始终为非负数并以,字符结尾,您可以使用:

int num = stream.ReadByte() - '0';
byte next = (byte)stream.ReadByte();
while (next != ',')
{
    num = num * 10 + next - '0';
    next = (byte)stream.ReadByte();
}

此页面对 4 种技术进行了基准测试。最快的方法正如罗曼在上面写的那样:

y = 0;
for (int i = 0; i < s[x].Length; i++)
    y = y * 10 + (s[x][i] - '0');

以下是一些经过测试的其他方法,这些方法被证明几乎慢了 10 倍(其中"s"是作者用于转换的字符串数组(:

int.Parse(s[x]);
Int32.TryParse(s[x], out y);
Convert.ToInt32(s[x]);

Convert.ToInt32()使用Int32.Parse()(加入一些验证(。 Int32.Parse()反过来使用Number.Parse() .

实际实现的速度与你能得到的一样快,除非你对输入值有很好的了解(例如,你的输入总是固定数量的数字,它从来都不是十六进制,有一定的精度,它总是无符号的,等等(。

private unsafe static Boolean NumberToInt64(ref NumberBuffer number, ref Int64 value) {
    Int32 i = number.scale;
    if (i > Int64Precision || i < number.precision) {
        return false;
    }
    char* p = number.digits;
    BCLDebug.Assert(p != null, "");
    Int64 n = 0;
    while (--i >= 0) {
        if ((UInt64)n > (0x7FFFFFFFFFFFFFFF / 10)) {
            return false;
        }
        n *= 10;
        if (*p != ''0') {
            n += (Int32)(*p++ - '0');
        }
    }
    if (number.sign) {
        n = -n;
        if (n > 0) {
            return false;
        }
    }
    else {
        if (n < 0) {
            return false;
        }
    }
    value = n;
    return true;
}

我在自己的基本框架中广泛使用Convert.ToXYZ()方法,在探查器会话中,即使在单个操作中调用数百次(例如反序列化复杂对象树(,它们也表示微不足道的开销。

我遇到过可以使用专用算法提高 BCL 性能的地方,但这可能不是其中之一。