[英]Faster alternative to Convert.ToDouble(string)
Is there a faster way to convert a string
to double
than Convert.ToDouble
?有没有比
Convert.ToDouble
更快的将string
转换为double
?
I have monitored System.Convert.ToDouble(string)
calls and its degrading my app performance.我已经监控了
System.Convert.ToDouble(string)
调用及其降低了我的应用程序性能。
Convert.ToDouble("1.34515");
WORKING ANSWER FROM Jeffrey Sax :杰弗里萨克斯的工作答案:
static decimal[] decimalPowersOf10 = { 1m, 10m, 100m, 1000m, 10000m, 100000m, 1000000m };
static decimal CustomParseDecimal(string input) {
long n = 0;
int decimalPosition = input.Length;
for (int k = 0; k < input.Length; k++) {
char c = input[k];
if (c == '.')
decimalPosition = k + 1;
else
n = (n * 10) + (int)(c - '0');
}
return n / decimalPowersOf10[input.Length - decimalPosition];
} }
You can save about 10% by calling Double.TryParse
with specific cached instances of NumberStyles
and IFormatProvider
(ie CultureInfo
):通过使用
NumberStyles
和IFormatProvider
特定缓存实例(即CultureInfo
)调用Double.TryParse
可以节省大约 10%:
var style = System.Globalization.NumberStyles.AllowDecimalPoint;
var culture = System.Globalization.CultureInfo.InvariantCulture;
double.TryParse("1.34515", style, culture, out x);
Both Convert.ToDouble
and Double.Parse
or Double.TryParse
have to assume the input can be in any format. Convert.ToDouble
和Double.Parse
或Double.TryParse
都必须假设输入可以是任何格式。 If you know for certain that your input has a specific format, you can write a custom parser that performs much better.如果您确定您的输入具有特定格式,您可以编写一个性能更好的自定义解析器。
Here's one that converts to decimal
.这是一个转换为
decimal
。 Conversion to double
is similar.转换为
double
是类似的。
static decimal CustomParseDecimal(string input) {
long n = 0;
int decimalPosition = input.Length;
for (int k = 0; k < input.Length; k++) {
char c = input[k];
if (c == '.')
decimalPosition = k + 1;
else
n = (n * 10) + (int)(c - '0');
}
return new decimal((int)n, (int)(n >> 32), 0, false, (byte)(input.Length - decimalPosition));
}
My benchmarks show this to be about 5 times faster than the original for decimal
, and up to 12 times if you use ints.我的基准测试表明这比原始的
decimal
快约 5 倍,如果使用 ints 则高达 12 倍。
I'm unable to reproduce this.我无法重现这一点。 This code tests the speed of
Convert.ToDouble
.此代码测试
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通过 10,000 个电话,我得到
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
.问题极不可能出在
Convert.ToDouble
。
You can call double.Parse("1.34515");
你可以调用
double.Parse("1.34515");
which is what Convert.ToDouble
wraps.这就是
Convert.ToDouble
包装的内容。
It may be quicker to call double.TryParse
which will avoid the exception overhead.调用
double.TryParse
可能会更快,这将避免异常开销。
Function in this post Faster alternative to decimal.Parse is based on Jeffrey Sax's code.这篇文章中的函数Faster替代decimal.Parse基于Jeffrey Sax的代码。 It adds support for negative numbers, optimizes performance by caching input.Length into a variable and works also for larger numbers.
它增加了对负数的支持,通过将 input.Length 缓存到变量中来优化性能,并且也适用于更大的数字。
You could try decreasing the number of calls to Thread.CurrentCulture
by using the Double.Parse(String, NumberStyles, IFormatProvider)
overload .您可以尝试使用
Double.Parse(String, NumberStyles, IFormatProvider)
重载来减少对Thread.CurrentCulture
的调用次数。 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.可能会发生解析为另一种类型:
float
或decimal
可能会赢得几个百分比。
Kind of a mad idea, but... You could cache the NumberFormatInfo
instance and use reflection to call the internal System.Number.ParseDouble
directly.有点疯狂的想法,但是...您可以缓存
NumberFormatInfo
实例并使用反射直接调用内部System.Number.ParseDouble
。 This would decrease the number of calls to NumberFormatInfo.GetInstance()
, but to be honest, I'd expect reflection to be much slower.这会减少对
NumberFormatInfo.GetInstance()
的调用次数,但老实说,我希望反射会慢得多。
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 (eg
#.####
), 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
.我对 .NET 代码进行了更多分析,发现
NumberFormatInfo
是一个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.如果您解析大量字符串对,您还可以将
IFormatProvider
缓存提取到(可能)运行循环并赢得另外几毫秒的外部代码。
double.Parse()
应该快一点。
If you are 100% sure about your source data format and range, you can use:如果您 100% 确定您的源数据格式和范围,您可以使用:
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.对我来说,它比
Double.Parse
快约 50%,但我不会在任何严肃的应用程序中使用它 - 与正确的解析相比,它非常有限,我想不出需要解析数百万双打和一个的过程几毫秒就会有所作为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.