Faster alternative to Convert.ToDouble(string)

前端 未结 7 2297
陌清茗
陌清茗 2020-12-17 23:35

Is there a faster way to convert a string to double than Convert.ToDouble?

I have monitored System.Conv

相关标签:
7条回答
  • 2020-12-17 23:56

    double.Parse() should be a little bit faster.

    0 讨论(0)
  • 2020-12-18 00:15

    I'm unable to reproduce this. This code tests the speed of Convert.ToDouble.

            int numTests = 10000;
            double sum = 0;
            var sw = Stopwatch.StartNew();
            for (int i = 0; i < numTests; ++i)
            {
                var d = Convert.ToDouble("1.23456");
                sum += d;
            }
            sw.Stop();
            Console.WriteLine("{0} tests @ {1} ms. Avg of {2:N4} ms each", numTests,
               sw.ElapsedMilliseconds, (double)sw.ElapsedMilliseconds/numTests);
            Console.WriteLine("sum = {0}", sum);
    

    With 10,000 calls, I get

    10000 tests @ 3 ms. Avg of 0.0003 ms each
    sum = 12345.6000000021
    

    That's in release mode, running without the debugger attached.

    It's highly unlikely that the problem is with Convert.ToDouble.

    0 讨论(0)
  • 2020-12-18 00:16

    If you are 100% sure about your source data format and range, you can use:

    string num = "1.34515";
    int len = num.Length - num.IndexOf('.') - 1;
    int intval = Int32.Parse(num.Replace(".", ""));
    double d = (double)intval / PowersOf10[len]; // PowersOf10 is pre-computed or inlined
    

    It worked ~50% faster than Double.Parse for me, but I wouldn't use it in any serious applications - it's extremely limited compared to proper parsing and I can't think of process where you need to parse millions of doubles and a few milliseconds would make the difference.

    0 讨论(0)
  • 2020-12-18 00:17

    You can call double.Parse("1.34515"); which is what Convert.ToDouble wraps.

    It may be quicker to call double.TryParse which will avoid the exception overhead.

    0 讨论(0)
  • 2020-12-18 00:17

    You could try decreasing the number of calls to Thread.CurrentCulture by using the Double.Parse(String, NumberStyles, IFormatProvider) overload. Although I doubt it would make a significant difference.

    It may occur that parsing to another type: float or decimal may win a couple percent.

    Kind of a mad idea, but... You could cache the NumberFormatInfo instance and use reflection to call the internal System.Number.ParseDouble directly. This would decrease the number of calls to NumberFormatInfo.GetInstance(), but to be honest, I'd expect reflection to be much slower.

    The only option left (except for avoiding parsing) is using some custom parsing method. For example, if you define a strict format for the numbers (e.g. #.####), you could probably end up with a faster, yet less flexible and/or safe implementation. But taking into account that built-in parsing is half-native, I doubt you'll win.

    UPDATE

    I've analyzed the .NET code a bit more and found out that NumberFormatInfo is a IFormatProvider. So it seems like the fastest code should be:

    IFormatProvider _CachedProvider = NumberFormatInfo.CurrentInfo;
    var value1 = double.Parse(str1, NumberStyles.Number, _CachedProvider);
    var value2 = double.Parse(str2, NumberStyles.Number, _CachedProvider);
    

    This code should decrease the time spent for parsing preparation as much as it's possible. If you parse a lot of string pairse, you could also extract the IFormatProvider caching to an external code that (possibly) runs a loop and win another couple of milliseconds.

    0 讨论(0)
  • 2020-12-18 00:20

    Function in this post Faster alternative to decimal.Parse is based on Jeffrey Sax's code. It adds support for negative numbers, optimizes performance by caching input.Length into a variable and works also for larger numbers.

    0 讨论(0)
提交回复
热议问题