关于C#:告诉字符串to double/float/int/short/byte是否超出范围

Tell if string to double/float/int/short/byte is out of range

有以下:

1
string outOfRange ="2147483648"; // +1 over int.MaxValue

很明显,如果你拥有比其他任何一个号码:这将失败。

1
2
var defaultValue = 0;
int.TryParse(outOfRange, out defaultValue);

我的问题是,由于这是一个数,它会让你int.TryParse()失败,你怎么说,这是因为失败的串出的出格的集装箱的仓库?


对于这种情况,我将使用Try/Catch解决方案。

1
2
3
4
5
6
7
8
9
10
11
        string outOfRange ="2147483648";
        try
        {
            int.Parse(outOfRange);
        }
        catch (OverflowException oex)
        {

        }
        catch (Exception ex)
        { }

我知道这里的大多数人都会建议避免这种情况,但有时我们只需要使用它(或者我们不必这样做,但它会节省我们很多时间)。这里有一篇关于Try/Catch效率的文章。


可以解析为十进制,然后检查范围,避免Try/Catch

1
2
string s ="2147483648";
decimal.Parse(s) > int.MaxValue;


您可以尝试使用BigInteger进行解析。

1
2
3
4
5
6
7
8
BigInteger bigInt;
bool isAnOutOfRangeInt = BigInteger.TryParse(input, out bigInt)
                         && (bigInt > int.MaxValue || bigInt < int.MinValue);
// if you care to have the value as an int:
if (!isAnOutOfRangeInt)
{
    int intValue = (int)bigInt;
}


我会尝试解析,如果失败,然后尝试解析更高的容量值。如果较高的容量值通过了解析,那么您就知道它超出了范围。如果它也失败了,那就是输入错误。

1
2
3
4
5
6
7
8
9
10
string outOfRange ="2147483648"; // +1 over int.MaxValue
int result;
if (!Int32.TryParse(outOfRange, out result))
{
    long rangeChecker;
    if (Int64.TryParse(outOfRange, out rangeChecker))
        //out of range
    else
        //bad format
}

不幸的是,我认为没有一种方法可以对任何类型进行一般性的这样做;您必须为所有类型编写一个实现。例如,对Int64做什么?可以用BigInteger代替:

1
2
3
4
5
6
7
8
9
10
string outOfRange ="9223372036854775808"; // +1 over Int64.MaxValue
long result;
if (!Int64.TryParse(outOfRange, out result))
{
    BigInteger rangeChecker;
    if (BigInteger.TryParse(outOfRange, out rangeChecker))
        //out of range
    else
        //bad format
}

编辑:double浮点值可能会更有趣,因为afaik没有"bigdecimal",您可能还需要考虑极端接近0的值(不确定)。可能您可以对BigInteger检查进行更改,但也可能需要考虑小数点(这里最好是一个简单的regex,只包含数字、可选的负号,最多只能有一个小数点)。如果有小数点,就必须将其截断,然后简单地检查字符串的整数部分。

editx2:这里还有一个非常丑陋的用于检查double值的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// +bajillion over Double.MaxValue
string outOfRange ="90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.1";
double result;
if (!Double.TryParse(outOfRange, out result))
{
    string bigIntegerInput = outOfRange;

    if (!Regex.IsMatch(bigIntegerInput, @"^-?[0-9]\d*(\.\d+)?$"))
        //bad format

    int decimalIndex = bigIntegerInput.IndexOf('.');
    if (decimalIndex > -1)
        bigIntegerInput = bigIntegerInput.Substring(0, decimalIndex);

    BigInteger rangeChecker;
    if (BigInteger.TryParse(bigIntegerInput, out rangeChecker))
        //out of range
    else
        //bad format
}

但老实说,在这一点上,我认为我们已经走到了尽头。除非您有一些真正的性能瓶颈,或者您的应用程序经常输入超出范围的值,否则您最好只在这个答案中出现的奇怪时间捕捉它们,或者更简单地说,将regex应用于输入。在上一个例子中,我可能在做了regex之后就退出了(但是如果TryParse的实现更为宽松,允许指数/科学记数法,我不太清楚。如果是这样,正则表达式也必须包含这些内容)


1
2
3
4
5
6
7
8
9
10
11
string outOfRange ="2147483648"; // +1 over int.MaxValue
int value;
if(! int.TryParse(outOfRange, out value)) {
    try {
        int.Parse(defaultValue);
    } catch(OverflowException e) {
        // was overflow
    } catch(Exception e) {
        // was other reason
    }
}

假设在数量太大的情况下很少发生,那么抛出和捕获异常的开销可能是可以容忍的,因为正常情况是用更快的TryParse方法处理的,而不涉及异常。

这对于其他数字数据类型(如float,…)的工作方式类似。


我将研究使用System.Convert.ToInt32(字符串)作为转换事物的机制;也就是说,因为已经为您实现了溢出异常。

这很方便,因为你可以做一些简单的事情

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 try
 {
      result = Convert.ToInt32(value);
      Console.WriteLine("Converted the {0} value '{1}' to the {2} value {3}.",
                    value.GetType().Name, value, result.GetType().Name, result);
 }
 catch (OverflowException)
 {
      Console.WriteLine("{0} is outside the range of the Int32 type.", value);
 }  
 catch (FormatException)
 {
      Console.WriteLine("The {0} value '{1}' is not in a recognizable format.",
                    value.GetType().Name, value);
 }

逻辑已经是标准系统库的一部分了。


使用正常的Parse而不是TryParse。然后在try/catch中使用它,因为它将为您提供适当的异常。有关详细信息,请参阅:http://msdn.microsoft.com/en-us/library/b3h1hf19.aspx。您要查找的异常是溢出异常。


直接前进的方法是使用int32.parse(string s)和catch OverflowException

OverflowException
s represents a number less than MinValue or greater than MaxValue.