繁体   English   中英

C#Double.ToString()性能问题

[英]C# Double.ToString() performance issue

我有以下方法将double数组转换为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 };

为了它的价值,我运行了以下内容并获得了不同的结果,十进制通常需要稍长一些(但是对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);

十进制和双数通常是混淆和互换的,但它们在处理器级别上是完全不同的动物。 如果我不得不想象为Double.ToString()编写代码,我可以看到问题......这很难。 相比之下,编写Decimal.ToString()的代码应该比Int32.ToString()困难得多。 我敢肯定,如果你将Int32.ToString()与Decimal.ToString()进行比较,你会发现它们的结果非常接近。

仅供参考:Double和Float(单曲)不精确,许多数字不能用Double表示。 在你的例子中,你给出1.2这实际上是1 + 1/5。 这不能作为一个真正的双重存在(即使VS IDE涵盖它)。 你会得到类似1.1999999999999998的东西。 如果您想要性能,请使用十进制。

2)为什么Decimal.ToString()比Double.ToString()快得多?

  1. 因为Double.ToString()实际上要复杂得多。 比较Decimal.ToString()Double.ToString()的核心实现, Decimal.ToString()具有固定的精度,而Double.ToString()的精度是按需的。 Double有它的IEEE浮点定义 ,它也比Decimal复杂得多。

  2. 当前的Double.ToString()实现依赖于Windows上的_ecvtLinux上的snprintf 它们效率低下(特别是对于Linux实现)。 有一个正在进行的PR以一种有效的方式重写Double.ToString() ,它消除了_ecvtsnprintf的依赖关系。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM