我有以下方法将双数组转换为List<string>
:
static Dest Test(Source s)
{
Dest d = new Dest();
if (s.A24 != null)
{
double[] dd = s.A24;
int cnt = dd.Length;
List<string> lst = new List<string>();
for (int i = 0; i < cnt; i++)
lst.Add(((double)dd[i]).ToString());
d.A24 = lst;
}
else
{
d.A24 = null;
}
return d;
}
根据我的基准测试,在循环中执行List.Add()似乎是最快的方法,可以击败所有各种LINQ和转换技巧。
这真的慢。一百万次呼叫2400ms(任何CPU,更喜欢64位)。所以我正在尝试各种方法来加快速度。让我们假设我无法缓存源列表或目标列表等。
所以无论如何,我偶然发现了一些奇怪的东西...如果我将lst.Add()行改为强制转换为十进制而不是双精度,那么它会更快,更快。 900毫秒vs 2400毫米。
这是我的问题
1)十进制具有更高的准确性然后加倍,所以我不应该在类型转换中丢失任何东西,对吗?
2)为什么Decimal.ToString()比Double.ToString()快得多?
3)这是一个合理的优化,还是我错过了一些重要的细节,这会让我咬伤?
我并不担心会占用更多的内存,我只关心性能。
此时测试数据没有任何复杂功能,只需使用:
s.A24 = new double[] { 1.2, 3.4, 5.6 };
答案 0 :(得分:2)
为了它的价值,我运行了以下内容并获得了不同的结果,十进制通常需要稍长一些(但是对lst.Add()和number.ToString()的调用都大致相同)。
代码中的A24是什么类型的集合?如果您看到的额外开销实际上是在投射或者您当前没有看到的东西,我不会感到惊讶。
var iterations = 1000000;
var lst = new List<string>();
var rnd = new Random();
var dblArray = new double[iterations];
for (var i = 0; i < iterations; i++)
//INTERESTING FINDING FROM THE COMMENTS
//double.ToString() is faster if this line is rnd.NextDouble()
//but decimal.ToString() is faster if hard-coding the value "3.5"
//(despite the overhead of casting to decimal)
dblArray[i] = rnd.NextDouble();
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < iterations; i++)
lst.Add(dblArray[i].ToString());
sw.Stop();
//takes 280-300 MS
Debug.WriteLine("Double loop MS: " + sw.ElapsedMilliseconds);
//reset list
lst = new List<string>();
sw.Restart();
for (var i = 0; i < iterations; i++)
lst.Add(((decimal)dblArray[i]).ToString());
sw.Stop();
//takes 280-320 MS
Debug.WriteLine("Decimal loop MS: " + sw.ElapsedMilliseconds);
答案 1 :(得分:1)
十进制和双数通常是混淆和互换的,但它们在处理器级别上是完全不同的动物。如果我不得不想象为Double.ToString()编写代码,我可以看到问题......这很难。相比之下,编写Decimal.ToString()的代码应该比Int32.ToString()困难得多。我敢肯定,如果你将Int32.ToString()与Decimal.ToString()进行比较,你会发现它们的结果非常接近。
仅供参考:Double和Float(单曲)不准确,许多数字不能用Double表示。在你的例子中,你给出1.2这实际上是1 + 1/5。这不能作为一个真正的双重存在(即使VS IDE涵盖它)。你会得到类似1.1999999999999998的东西。如果您想要性能,请使用十进制。
答案 2 :(得分:1)
2)为什么Decimal.ToString()比Double.ToString()快得多?
因为Double.ToString()
实际上要复杂得多。比较Decimal.ToString()和Double.ToString()的核心实现,Decimal.ToString()
具有固定的精度,而Double.ToString()
的精度是按需的。 Double
有IEEE floating point definition,它比Decimal
复杂得多。
当前的Double.ToString()
实施依赖于Windows上的_ecvt
和snprintf
on Linux。它们效率低下(特别是对于Linux实现)。我需要in-progress PR以有效的方式重写Double.ToString()
,以消除_ecvt
和snprintf
的依赖关系。