判断double / float / int / short / byte的字符串是否超出范围

时间:2022-04-30 16:43:28

I have the following:

我有以下内容:

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

Obviously if you have anything other than a number this will fail:

显然,如果你有一个数字以外的东西,这将失败:

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

My question is, since this IS a number, and it WILL fail when you int.TryParse(), how do you tell that it failed because the string was out of the bounds of the container it's stored in?

我的问题是,因为这是一个数字,并且当你int.TryParse()时它会失败,你如何告诉它失败,因为字符串超出了它存储在容器的边界?

8 个解决方案

#1


2  

I would attempt to parse, if it fails, then attempt to parse a higher-capacity value. If the higher capacity value passes parsing, then you know it's out of range. If it fails as well, then it's bad input.

我会尝试解析,如果失败,则尝试解析更高容量的值。如果较高容量值通过解析,那么您知道它超出范围。如果它也失败了,那么它输入不好。

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
}

Unfortunately, I don't think there's a way to do this generically for any type; you'd have to write an implementation for all types. So for example, what do do for Int64? Maybe use BigInteger instead:

不幸的是,我认为没有办法对任何类型的一般做这件事;你必须为所有类型编写一个实现。那么,例如,Int64做了什么?也许使用BigInteger代替:

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
}

EDIT: double floating point values may be more fun since AFAIK, there's no "BigDecimal" and you may have to also account for values that approach 0 at the very extreme (not sure about that). Possibly you could do a variation on the BigInteger check but you might also have to account for decimal points (probably a simple regex would be best here to have only numbers, an optional negative sign, and only one at most decimal point). If there are any decimal points, you'd have to truncate them out and simply check the integer portion of the string.

编辑:自AFAIK以来,双浮点值可能更有趣,没有“BigDecimal”,您可能还必须考虑极端接近0的值(不确定)。可能你可以对BigInteger检查做一个变化,但你可能还需要考虑小数点(可能一个简单的正则表达式最好只有数字,一个可选的负号,最多只有一个小数点)。如果有任何小数点,则必须将它们截断并简单地检查字符串的整数部分。

EDITx2: Here's a pretty ugly implementation for checking double values too:

EDITx2:这是一个非常难看的实现,用于检查double值:

// +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
}

But honestly, at this point I think we've just gone off the deep end. Unless you have some real performance bottleneck, or your application has out-of-range values inputted frequently, you might be better off just catching them the odd time it happens as in this answer or perhaps more simply, applying a regex to the input. In my last example, I may have as well just quit after doing the regex anyway (but I don't know off the top of my head if the TryParse implementations are more lenient, allowing for exponential/scientific notation. If so, the regex would have to cover these as well)

但老实说,在这一点上,我认为我们刚刚走出了尽头。除非你有一些真正的性能瓶颈,或者你的应用程序经常输入超出范围的值,你可能最好只是捕捉它们在这个答案中发生的奇怪时间,或者更简单地说,将正则表达式应用于输入。在我的最后一个例子中,我也可以在完成正则表达式之后退出(但是如果TryParse实现更宽松,我不知道我的头脑,允许指数/科学表示法。如果是这样,正则表达式也必须覆盖这些)

#2


4  

I'd go with the Try/Catch solution for this scenario.

我会使用此方案的Try / Catch解决方案。

        string outOfRange = "2147483648";
        try
        {
            int.Parse(outOfRange);
        }
        catch (OverflowException oex)
        {

        }
        catch (Exception ex)
        { }

I know that most people here would recommend avoiding this but sometimes we just have to use it (or we don't have to but it would just save us a lot of time).
here's a little post about the efficiency of Try/Catch.

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

#3


3  

can parse to decimal and then check range, avoids try/catch

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

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

#4


2  

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
    }
}

Assuming that there are few cases where the number is too large, the overhead of exception throwing and catching may be tolerable, as the normal cases are handled with the faster TryParse method without involving exceptions.

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

This would work similar for other numeric data types like floats, ...

这与其他数字数据类型(如浮点数)类似,...

#5


2  

You could try parsing with BigInteger.

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

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;
}

#6


1  

Use the normal Parse instead of the TryParse. And then use it inside a try/catch because it will give you the appropriate exception. See this for details: http://msdn.microsoft.com/en-us/library/b3h1hf19.aspx. The exception you are looking for is OverflowException.

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

#7


1  

I would look at using System.Convert.ToInt32(String) as the mechanism to convert things; namely because OverflowException has already been implemented for you.

我会看看使用System.Convert.ToInt32(String)作为转换事物的机制;因为已经为您实现了OverflowException。

This is convenient because you can do something simple like

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

 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);
 }   

and the logic is already a part of the standard System library.

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

#8


0  

The straight forward way would be to instead use Int32.Parse(string s) and catch OverflowException;

直接的方法是使用Int32.Parse(string s)并捕获OverflowException;

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

OverflowException s表示小于MinValue或大于MaxValue的数字。

#1


2  

I would attempt to parse, if it fails, then attempt to parse a higher-capacity value. If the higher capacity value passes parsing, then you know it's out of range. If it fails as well, then it's bad input.

我会尝试解析,如果失败,则尝试解析更高容量的值。如果较高容量值通过解析,那么您知道它超出范围。如果它也失败了,那么它输入不好。

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
}

Unfortunately, I don't think there's a way to do this generically for any type; you'd have to write an implementation for all types. So for example, what do do for Int64? Maybe use BigInteger instead:

不幸的是,我认为没有办法对任何类型的一般做这件事;你必须为所有类型编写一个实现。那么,例如,Int64做了什么?也许使用BigInteger代替:

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
}

EDIT: double floating point values may be more fun since AFAIK, there's no "BigDecimal" and you may have to also account for values that approach 0 at the very extreme (not sure about that). Possibly you could do a variation on the BigInteger check but you might also have to account for decimal points (probably a simple regex would be best here to have only numbers, an optional negative sign, and only one at most decimal point). If there are any decimal points, you'd have to truncate them out and simply check the integer portion of the string.

编辑:自AFAIK以来,双浮点值可能更有趣,没有“BigDecimal”,您可能还必须考虑极端接近0的值(不确定)。可能你可以对BigInteger检查做一个变化,但你可能还需要考虑小数点(可能一个简单的正则表达式最好只有数字,一个可选的负号,最多只有一个小数点)。如果有任何小数点,则必须将它们截断并简单地检查字符串的整数部分。

EDITx2: Here's a pretty ugly implementation for checking double values too:

EDITx2:这是一个非常难看的实现,用于检查double值:

// +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
}

But honestly, at this point I think we've just gone off the deep end. Unless you have some real performance bottleneck, or your application has out-of-range values inputted frequently, you might be better off just catching them the odd time it happens as in this answer or perhaps more simply, applying a regex to the input. In my last example, I may have as well just quit after doing the regex anyway (but I don't know off the top of my head if the TryParse implementations are more lenient, allowing for exponential/scientific notation. If so, the regex would have to cover these as well)

但老实说,在这一点上,我认为我们刚刚走出了尽头。除非你有一些真正的性能瓶颈,或者你的应用程序经常输入超出范围的值,你可能最好只是捕捉它们在这个答案中发生的奇怪时间,或者更简单地说,将正则表达式应用于输入。在我的最后一个例子中,我也可以在完成正则表达式之后退出(但是如果TryParse实现更宽松,我不知道我的头脑,允许指数/科学表示法。如果是这样,正则表达式也必须覆盖这些)

#2


4  

I'd go with the Try/Catch solution for this scenario.

我会使用此方案的Try / Catch解决方案。

        string outOfRange = "2147483648";
        try
        {
            int.Parse(outOfRange);
        }
        catch (OverflowException oex)
        {

        }
        catch (Exception ex)
        { }

I know that most people here would recommend avoiding this but sometimes we just have to use it (or we don't have to but it would just save us a lot of time).
here's a little post about the efficiency of Try/Catch.

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

#3


3  

can parse to decimal and then check range, avoids try/catch

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

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

#4


2  

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
    }
}

Assuming that there are few cases where the number is too large, the overhead of exception throwing and catching may be tolerable, as the normal cases are handled with the faster TryParse method without involving exceptions.

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

This would work similar for other numeric data types like floats, ...

这与其他数字数据类型(如浮点数)类似,...

#5


2  

You could try parsing with BigInteger.

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

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;
}

#6


1  

Use the normal Parse instead of the TryParse. And then use it inside a try/catch because it will give you the appropriate exception. See this for details: http://msdn.microsoft.com/en-us/library/b3h1hf19.aspx. The exception you are looking for is OverflowException.

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

#7


1  

I would look at using System.Convert.ToInt32(String) as the mechanism to convert things; namely because OverflowException has already been implemented for you.

我会看看使用System.Convert.ToInt32(String)作为转换事物的机制;因为已经为您实现了OverflowException。

This is convenient because you can do something simple like

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

 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);
 }   

and the logic is already a part of the standard System library.

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

#8


0  

The straight forward way would be to instead use Int32.Parse(string s) and catch OverflowException;

直接的方法是使用Int32.Parse(string s)并捕获OverflowException;

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

OverflowException s表示小于MinValue或大于MaxValue的数字。