更快的替代decimal.Parse [英] Faster alternative to decimal.Parse
问题描述
我注意到 decimal.Parse(数字,NumberStyles.AllowDecimalPoint,CultureInfo.InvariantCulture)
比定制小数解析方法要慢约100%的基础上,从<一杰弗里·萨克斯的代码HREF =http://stackoverflow.com/questions/8457934/faster-alternative-to-convert-todouble>更快的替代Convert.ToDouble
I noticed decimal.Parse(number, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture)
is about 100% slower than custom decimal parse method based on Jeffrey Sax's code from Faster alternative to Convert.ToDouble
public static decimal ParseDecimal(string input) {
bool negative = false;
long n = 0;
int len = input.Length;
int decimalPosition = len;
if (len != 0) {
int start = 0;
if (input[0] == '-') {
negative = true;
start = 1;
}
for (int k = start; k < len; 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, negative, (byte)(len -decimalPosition));
}
我认为,这是因为本地 decimal.Parse
设计有一些风格和文化信息的斗争。
I assume that is because native decimal.Parse
is designed to struggle with number style and culture info.
不过,上述方法不<$ C $使用第3个参数喜字节C>新小数所以不会有较大的数字工作。
However, above mentioned method doesn't use 3rd parameter hi byte in new decimal
so it won't work with larger numbers.
有没有小数更快的替代方案。 ?解析
来的字符串,仅由数字和小数点点,以十进制这将有大量的工作转换
Is there a faster alternative to decimal.Parse
to convert string that consists only of numbers and decimal dot to decimal which would work with large numbers?
编辑:基准:
var style = System.Globalization.NumberStyles.AllowDecimalPoint;
var culture = System.Globalization.CultureInfo.InvariantCulture;
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
s.Reset();
s.Start();
for (int i=0; i<10000000; i++)
{
decimal.Parse("20000.0011223344556", style, culture);
}
s.Stop();
Console.WriteLine(s.Elapsed.ToString());
s.Reset();
s.Start();
for (int i=0; i<10000000; i++)
{
ParseDecimal("20000.0011223344556");
}
s.Stop();
Console.WriteLine(s.Elapsed.ToString());
输出:
output:
00:00:04.2313728
00:00:01.4464048
自定义ParseDecimal在这种情况下比decimal.Parse显著快。
Custom ParseDecimal is in this case significantly faster than decimal.Parse.
推荐答案
感谢您的意见这给了我一个小更深入的了解。最后我做到了如下。如果输入太长,那么它分开输入字符串,并使用长和INT剩下的这仍然比decimal.Parse更快的解析第一部分。
Thanks for all your comments which gave me a little more insight. Finally I did it as follows. If input is too long then it separates input string and parses first part using long and the rest with int which is still faster than decimal.Parse.
这是我最后的生产代码:
This is my final production code:
public static int[] powof10 = new int[10]
{
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};
public static decimal ParseDecimal(string input)
{
int len = input.Length;
if (len != 0)
{
bool negative = false;
long n = 0;
int start = 0;
if (input[0] == '-')
{
negative = true;
start = 1;
}
if (len <= 19)
{
int decpos = len;
for (int k = start; k < len; k++)
{
char c = input[k];
if (c == '.')
{
decpos = k +1;
}else{
n = (n *10) +(int)(c -'0');
}
}
return new decimal((int)n, (int)(n >> 32), 0, negative, (byte)(len -decpos));
}else{
if (len > 28)
{
len = 28;
}
int decpos = len;
for (int k = start; k < 19; k++)
{
char c = input[k];
if (c == '.')
{
decpos = k +1;
}else{
n = (n *10) +(int)(c -'0');
}
}
int n2 = 0;
bool secondhalfdec = false;
for (int k = 19; k < len; k++)
{
char c = input[k];
if (c == '.')
{
decpos = k +1;
secondhalfdec = true;
}else{
n2 = (n2 *10) +(int)(c -'0');
}
}
byte decimalPosition = (byte)(len -decpos);
return new decimal((int)n, (int)(n >> 32), 0, negative, decimalPosition) *powof10[len -(!secondhalfdec ? 19 : 20)] +new decimal(n2, 0, 0, negative, decimalPosition);
}
}
return 0;
}
基准代码:
benchmark code:
const string input = "[inputs are below]";
var style = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign;
var culture = System.Globalization.CultureInfo.InvariantCulture;
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
s.Reset();
s.Start();
for (int i=0; i<10000000; i++)
{
decimal.Parse(input, style, culture);
}
s.Stop();
Console.WriteLine(s.Elapsed.ToString());
s.Reset();
s.Start();
for (int i=0; i<10000000; i++)
{
ParseDecimal(input);
}
s.Stop();
Console.WriteLine(s.Elapsed.ToString());
这是我的酷睿i7 920的结果:
results on my i7 920:
输入:123.456789
input: 123.456789
00:00:02.7292447
00:00:00.6043730
输入:999999999999999123.456789
input: 999999999999999123.456789
00:00:05.3094786
00:00:01.9702198
输入:1.0
00:00:01.4212123
00:00:00.2378833
输入:0
00:00:01.1083770
00:00:00.1899732
输入:-3.3333333333333333333333333333333
input: -3.3333333333333333333333333333333
00:00:06.2043707
00:00:02.0373628
如果输入只包含0-9。和可选的 - 在开始时那么这个自定义函数显著更快解析字符串到十进制
If input consists only of 0-9, . and optionally - at the begining then this custom function is significantly faster for parsing string to decimal.
这篇关于更快的替代decimal.Parse的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!