2012-02-15 78 views
3

到int的任何更有效的方法是否有转换的字符串整数到int,而不是在用c#Convert.ToInt32()的更有效的方法?转换字符串整数比convert.toint32

我有一个程序,将大量的字符串转换为整数。这些值是以字符串格式从文本文件中读取的。

+0

没有符合你尝试使用'Int.Parse()'? – Marco 2012-02-15 19:27:14

+1

目前速度有多快,你需要多快? (我个人使用'int.Parse'或'int.TryParse',但没有太大区别。) – 2012-02-15 19:27:26

+0

你对字符串的长度有任何限制吗? – Douglas 2012-02-15 19:27:43

回答

1

如果你从一个Stream读你的整数,那么你可以通过避免初始化字符串的开销优化。

例如,假设您的号码将始终非负,并通过,字符结尾,你可以使用:

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

不,可能不会,至少不会比他强得多。我尝试这个快速和肮脏的基准:

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 S启用,或13%的改善,而住根本不正确

+2

您可能想要使用秒表类... – 2012-02-15 19:47:51

+1

如果发生在内循环中,40%可能是一个非常重要的改进。 – 2015-02-03 21:52:02

+0

@EricJ。当然,如果你能免费得到它,40%是好的。但是,在这种情况下,您可以根据具体情况来换取可能不正确的行为,这可能会或可能不会被接受。 – dasblinkenlight 2015-02-03 22:37:37

0

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的一个专门的算法的性能改善,但这可能不是其中之一。

2

使用这种方法:

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的转换。

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

1

This page基准4层的技术。最快的方法如罗曼写以上:

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

这里有一些other methods that were tested被证明几乎10倍慢(其中“s”是一个字符串数组中使用的作者的换算表):

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