将字符串整数转换为 int 的任何比 convert.toint32 更有效的方法
本文关键字:toint32 convert 有效 方法 任何比 整数 转换 int 字符串 | 更新日期: 2023-09-27 18:24:57
有没有比在 c# 中使用 Convert.ToInt32()
更有效的方法将字符串整数转换为 int?
我有一个程序可以将很多字符串转换为整数。 这些值以字符串格式从文本文件中读取。
不,可能不是,至少到目前为止不是。我尝试了这个快速而肮脏的基准测试:
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 性能的地方,但这可能不是其中之一。