如何在C#中以指数格式查找字符串值?

时间:2020-12-30 19:24:16

I want to find whether string has exponential format or not. Currently i am checking like below.

我想找出字符串是否具有指数格式。目前我正在检查如下。

var s = "1.23E+04";
var hasExponential = s.Contains("E");

But i know this is not the proper way. So can anyone please guide proper and fastest way to achieve my requirement?

但我知道这不是正确的方法。那么有人可以指导正确和快速的方式来达到我的要求吗?

3 个解决方案

#1


6  

If you also want to make sure it really is a number, not just a string with an 'E' in it, maybe a function like this can be helpful. The logic remains simple.

如果你还想确保它确实是一个数字,而不仅仅是一个带有'E'的字符串,那么这样的函数可能会有所帮助。逻辑仍然很简单。

private bool IsExponentialFormat(string str)
{
    double dummy;
    return (str.Contains("E") || str.Contains("e")) && double.TryParse(str, out dummy);
}

#2


1  

Try to use regular expression?

尝试使用正则表达式?

string s = "1.23E+04";
string pattern = @"^\d{1}.\d+(E\+)\d+$";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
bool hasExponential = rgx.IsMatch(s);

#3


0  

You could always split on e. Or use double.TryParse. Both work pretty well. (I would bet the ParseExponential2 is faster for valid ones, whereas ParseExponential1 could be faster for invalid ones.)

你可以随时拆分e。或者使用double.TryParse。两者都很好用。 (我敢打赌ParseExponential2对于有效的更快,而ParseExponential1对于无效的更快。)

public static void _Main(string[] args)
{
    string[] exponentials = new string[] { "1.23E+4", "1.23E+04", "1.23e+4", "1.23", "1.23e+4e+4", "abce+def", "1.23E-04" };

    for (int i = 0; i < exponentials.Length; i++)
        Console.WriteLine("Input: {0}; Result 1: {1}; Result 2: {2}; Result 3: {3}", exponentials[i], (ParseExponential1(exponentials[i]) ?? 0), (ParseExponential2(exponentials[i]) ?? 0), (ParseExponential3(exponentials[i]) ?? 0));
}

public static double? ParseExponential1(string input)
{
    if (input.Contains("e") || input.Contains("E"))
    {
        string[] inputSplit = input.Split(new char[] { 'e', 'E' });

        if (inputSplit.Length == 2) // If there were not two elements split out, it's an invalid exponential.
        {
            double left = 0;
            int right = 0;

            if (double.TryParse(inputSplit[0], out left) && int.TryParse(inputSplit[1], out right) // Parse the values
                && (left >= -5.0d && left <= 5.0d && right >= -324) // Check that the values are within the range of a double, this is the minimum.
                && (left >= -1.7d && left <= 1.7d && right <= 308)) // Check that the values are within the range of a double, this is the maximum.
            {
                double result = 0;

                if (double.TryParse(input, out result))
                    return result;
            }
        }
    }

    return null;
}

public static double? ParseExponential2(string input)
{
    if (input.Contains("e") || input.Contains("E"))
    {
        double result = 0;

        if (double.TryParse(input, out result))
            return result;
    }

    return null;
}

public static double? ParseExponential3(string input)
{
    double result = 0;

    if (double.TryParse(input, out result))
        return result;

    return null;
}

If the ParseExponential1, ParseExponential2 or ParseExponential3 returns null, then it was invalid. This also allows you to parse it at the same time and get the value indicated.

如果ParseExponential1,ParseExponential2或ParseExponential3返回null,则它无效。这也允许您同时解析它并获得指示的值。

The only issue with ParseExponential3 is that it will also return valid numbers if they are not exponential. (I.e., for the 1.23 case it will return 1.23.)

ParseExponential3的唯一问题是,如果它们不是指数的,它也将返回有效数字。 (即,对于1.23的情况,它将返回1.23。)

You could also remove the checks for the double range. They are just there for completeness.

您还可以删除双范围的检查。他们只是为了完整性。

Also, to prove a point, I just ran a benchmark with the code below, and the Regex option in the other answer by nevermoi took 500ms to run 100,000 times over the exponentials array, the ParseExponential1 option took 547ms, and the ParseExponential2 option 317ms. The method by sstan took 346ms. Lastly, the fastest was my ParseExponential3 method at 134ms.

另外,为了证明这一点,我只是使用下面的代码运行基准测试,并且使用nevermoi的另一个答案中的Regex选项花了500ms在指数数组上运行100,000次,ParseExponential1选项需要547ms,ParseExponential2选项需要317ms。 sstan的方法耗时346ms。最后,最快的是我的ParseExponential3方法在134ms。

string[] exponentials = new string[] { "1.23E+4", "1.23E+04", "1.23e+4", "1.23", "1.23e+4e+4", "abce+def", "1.23E-04" };

Stopwatch sw = new Stopwatch();
sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        ParseExponential1(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 1 (ParseExponential1) complete: {0}ms", sw.ElapsedMilliseconds);

sw.Reset();

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        ParseExponential2(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 2 (ParseExponential2) complete: {0}ms", sw.ElapsedMilliseconds);
sw.Reset();
string pattern = @"^\d{1}.\d+(E\+)\d+$";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        rgx.IsMatch(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 3 (Regex Parse) complete: {0}ms", sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        IsExponentialFormat(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 4 (IsExponentialFormat) complete: {0}ms", sw.ElapsedMilliseconds);

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        ParseExponential3(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 5 (ParseExponential3) complete: {0}ms", sw.ElapsedMilliseconds);

And the following method was added:

并添加了以下方法:

private static bool IsExponentialFormat(string str)
{
    double dummy;
    return (str.Contains("E") || str.Contains("e")) && double.TryParse(str, out dummy);
}

#1


6  

If you also want to make sure it really is a number, not just a string with an 'E' in it, maybe a function like this can be helpful. The logic remains simple.

如果你还想确保它确实是一个数字,而不仅仅是一个带有'E'的字符串,那么这样的函数可能会有所帮助。逻辑仍然很简单。

private bool IsExponentialFormat(string str)
{
    double dummy;
    return (str.Contains("E") || str.Contains("e")) && double.TryParse(str, out dummy);
}

#2


1  

Try to use regular expression?

尝试使用正则表达式?

string s = "1.23E+04";
string pattern = @"^\d{1}.\d+(E\+)\d+$";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
bool hasExponential = rgx.IsMatch(s);

#3


0  

You could always split on e. Or use double.TryParse. Both work pretty well. (I would bet the ParseExponential2 is faster for valid ones, whereas ParseExponential1 could be faster for invalid ones.)

你可以随时拆分e。或者使用double.TryParse。两者都很好用。 (我敢打赌ParseExponential2对于有效的更快,而ParseExponential1对于无效的更快。)

public static void _Main(string[] args)
{
    string[] exponentials = new string[] { "1.23E+4", "1.23E+04", "1.23e+4", "1.23", "1.23e+4e+4", "abce+def", "1.23E-04" };

    for (int i = 0; i < exponentials.Length; i++)
        Console.WriteLine("Input: {0}; Result 1: {1}; Result 2: {2}; Result 3: {3}", exponentials[i], (ParseExponential1(exponentials[i]) ?? 0), (ParseExponential2(exponentials[i]) ?? 0), (ParseExponential3(exponentials[i]) ?? 0));
}

public static double? ParseExponential1(string input)
{
    if (input.Contains("e") || input.Contains("E"))
    {
        string[] inputSplit = input.Split(new char[] { 'e', 'E' });

        if (inputSplit.Length == 2) // If there were not two elements split out, it's an invalid exponential.
        {
            double left = 0;
            int right = 0;

            if (double.TryParse(inputSplit[0], out left) && int.TryParse(inputSplit[1], out right) // Parse the values
                && (left >= -5.0d && left <= 5.0d && right >= -324) // Check that the values are within the range of a double, this is the minimum.
                && (left >= -1.7d && left <= 1.7d && right <= 308)) // Check that the values are within the range of a double, this is the maximum.
            {
                double result = 0;

                if (double.TryParse(input, out result))
                    return result;
            }
        }
    }

    return null;
}

public static double? ParseExponential2(string input)
{
    if (input.Contains("e") || input.Contains("E"))
    {
        double result = 0;

        if (double.TryParse(input, out result))
            return result;
    }

    return null;
}

public static double? ParseExponential3(string input)
{
    double result = 0;

    if (double.TryParse(input, out result))
        return result;

    return null;
}

If the ParseExponential1, ParseExponential2 or ParseExponential3 returns null, then it was invalid. This also allows you to parse it at the same time and get the value indicated.

如果ParseExponential1,ParseExponential2或ParseExponential3返回null,则它无效。这也允许您同时解析它并获得指示的值。

The only issue with ParseExponential3 is that it will also return valid numbers if they are not exponential. (I.e., for the 1.23 case it will return 1.23.)

ParseExponential3的唯一问题是,如果它们不是指数的,它也将返回有效数字。 (即,对于1.23的情况,它将返回1.23。)

You could also remove the checks for the double range. They are just there for completeness.

您还可以删除双范围的检查。他们只是为了完整性。

Also, to prove a point, I just ran a benchmark with the code below, and the Regex option in the other answer by nevermoi took 500ms to run 100,000 times over the exponentials array, the ParseExponential1 option took 547ms, and the ParseExponential2 option 317ms. The method by sstan took 346ms. Lastly, the fastest was my ParseExponential3 method at 134ms.

另外,为了证明这一点,我只是使用下面的代码运行基准测试,并且使用nevermoi的另一个答案中的Regex选项花了500ms在指数数组上运行100,000次,ParseExponential1选项需要547ms,ParseExponential2选项需要317ms。 sstan的方法耗时346ms。最后,最快的是我的ParseExponential3方法在134ms。

string[] exponentials = new string[] { "1.23E+4", "1.23E+04", "1.23e+4", "1.23", "1.23e+4e+4", "abce+def", "1.23E-04" };

Stopwatch sw = new Stopwatch();
sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        ParseExponential1(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 1 (ParseExponential1) complete: {0}ms", sw.ElapsedMilliseconds);

sw.Reset();

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        ParseExponential2(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 2 (ParseExponential2) complete: {0}ms", sw.ElapsedMilliseconds);
sw.Reset();
string pattern = @"^\d{1}.\d+(E\+)\d+$";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        rgx.IsMatch(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 3 (Regex Parse) complete: {0}ms", sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        IsExponentialFormat(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 4 (IsExponentialFormat) complete: {0}ms", sw.ElapsedMilliseconds);

sw.Start();
for (int round = 0; round < 100000; round++)
    for (int i = 0; i < exponentials.Length; i++)
        ParseExponential3(exponentials[i]);
sw.Stop();
Console.WriteLine("Benchmark 5 (ParseExponential3) complete: {0}ms", sw.ElapsedMilliseconds);

And the following method was added:

并添加了以下方法:

private static bool IsExponentialFormat(string str)
{
    double dummy;
    return (str.Contains("E") || str.Contains("e")) && double.TryParse(str, out dummy);
}