在论坛上看到一个问题,两个字符串
string a = "1100100111001010111";
string b = "1010101101110110010";
求字符串 c,若 a 和 b 相对应的位有一个为 1,则 c 中该位置处的值为 1。例如在本题中 c = "1110101111111110111"。
有人回答:
- string a = "1100100111001010111";
- string b = "1010101101110110010";
- string c = "";
- int count = 1000000;
- DateTime start = DateTime.Now;
- for (int i = 1; i != count; ++i)
- {
- Int64 ia = Convert.ToInt64(a, 2);
- Int64 ib = Convert.ToInt64(b, 2);
- c = Convert.ToString((ia | ib), 2);
- }
- DateTime end = DateTime.Now;
上面的代码中我加了一个循环,用于计算时间开销。
当时只是觉得如果字符串太长超过64位时,会导致转换异常,所以自己重写了一个,直接对字符循环,然后比较,输出值
- string a = "1100100111001010111";
- string b = "1010101101110110010";
- string c = "";
- int count = 1000000;
- DateTime start = DateTime.Now;
- for (int i = 1; i != count; ++i)
- {
- int len = a.Length;
- System.Text.StringBuilder sb = new System.Text.StringBuilder();
- for (int j = 0; j != len; ++j)
- {
- if (a[j] == '1' || b[j] == '1')
- sb.Append('1');
- else
- sb.Append('0');
- }
- c = sb.ToString();
- }
- DateTime end = DateTime.Now;
这里我也加了个循环,用于计算时间开销。
开始的时候凭直觉认为上面那个算法应该会更快一些。但后来仔细想了一下,似乎不是这样子的,所以就做了个测试,结果如下:
第一个方法(循环100万次)花费时间:00:00:02.2821844 秒
第二个方法(循环100万次)花费时间:00:00:01.3130376 秒
第二个方法仅需要第一个方法一半多一点的时间,为什么会这样呢,直接进行或操作的速度应该更快才对?
其实问题的关键在于类型转换上,第一个方法在将字符串转换为整形值时使用了 Convert.ToInt64(a, 2),这个方法应该也是对字符串循环后通过移位操作而转换为整形的,所以在时间的开销上大于第二种方法也就不足为奇。
我在这里想说的是,我们在很多时候走入了一个误区,在潜意识中总认为 .NET 框架所提供的内置方法效率一定高,从而常常忽略这些内置方法所需要的时间开销,有时甚至为了迎合这些内置的方法而不惜对已有的数据结构进行转换(呵,常见的例子有 HashTable,Dictionary,Array,List 等的使用),当然,若是为了更方便的编程,这无可厚非,但有些时候本来就是为了获取更高的效率,那这样做是否真的能够达到想要的效果呢?(我曾经看到一个 C++ 的例子,本身要求的是对一个数组进行尽可能快的排序,可有些人坚持认为将数组转换为 Vector,然后用 Vector 内置的排序功能排序,这样是最快的,呵呵。)我们是不是应该多做些测试,再做定论呢。