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

Posted

技术标签:

【中文标题】判断字符串到 double/float/int/short/byte 是不是超出范围【英文标题】:Tell if string to double/float/int/short/byte is out of range判断字符串到 double/float/int/short/byte 是否超出范围 【发布时间】:2013-09-02 09:52:36 【问题描述】:

我有以下几点:

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

显然,如果您有除数字以外的任何内容,这将失败:

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

我的问题是,因为这是一个数字,当你 int.TryParse() 时它会失败,你怎么知道它失败是因为字符串超出了它存储的容器的范围?

【问题讨论】:

是否首先将其解析为更大的容量值(比如long,或者uint,如果你知道你只有正数)然后检查Int32.Max/MinValue是否可行? 我想这可能是一种解决方案。也许更通用的东西适用于任何容器类型。 您可以通过使用Try-Catch 并检查异常消息而不是int.TryParse 来获得一个想法 有什么用?如果是为了验证输入,则可能没有必要,考虑到您可以在消息中覆盖它,而不会产生许多不同消息的复杂性。如果是针对您无能为力的情况,那么请改用Parse 方法来允许发生异常,也许?只是我的好奇心和观察。 我同意@GrantThomas,从用户的角度来看,他们为什么要知道int 溢出+- 20 亿?用例应确定您期望的实际输入范围,您将根据该范围编写验证,并且您还将选择适当的数据类型。 【参考方案1】:

对于这种情况,我会选择 Try/Catch 解决方案。

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

        
        catch (Exception ex)
         

我知道这里的大多数人会建议避免使用它,但有时我们只需要使用它(或者我们不必使用它,但这只会为我们节省大量时间)。here's 一个小帖子关于Try/Catch的效率。

【讨论】:

【参考方案2】:

可以解析成十进制再检查范围,避免try/catch

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

【讨论】:

【参考方案3】:

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

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

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 检查进行变体,但您可能还必须考虑小数点(可能一个简单的正则表达式最好只有数字,一个可选的负号,并且最多只有一个 /em> 小数点)。如果有任何小数点,您必须将它们截断并简单地检查字符串的整数部分。

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

但老实说,在这一点上,我认为我们刚刚走到了尽头。除非您有一些真正的性能瓶颈,或者您的应用程序经常输入超出范围的值,否则您最好只在this answer 中发生的奇怪时间捕获它们,或者更简单,将 regex 应用于输入。在我的最后一个示例中,无论如何,我也可能在执行正则表达式后退出(但我不知道TryParse 实现是否更宽松,允许指数/科学符号。如果是这样,正则表达式也必须涵盖这些)

【讨论】:

【参考方案4】:
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方法处理而不涉及异常。

这对于其他数字数据类型(如浮点数、...

【讨论】:

不要对控制流使用异常。 您可以改用Int64.TryParse;如果它通过了,你就知道它超出了范围。如果它失败了,那么你就知道这是错误的输入。 @ChrisSinclair 但最初的问题还想知道长、双精度等的解决方案。 @It'sNotALie。在有效数字的标准情况下,没有例外。我认为溢出的情况至少部分是例外的。并且首先检查所有有效字符串的解决方案并不简单,特别是如果您想按照原始帖子的要求将其用于双打。因此,我在这里要说的是,使用异常是不使用异常进行控制流的规则的例外。【参考方案5】:

您可以尝试使用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;

【讨论】:

按照原帖的要求,您将如何将其用于doubles 而不是ints?【参考方案6】:

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

【讨论】:

既然可以使用TryParse的返回值,为什么还要使用异常来控制流? TryParse 返回一个bool,这与从Parse 中获取许多不同的异常不可比。【参考方案7】:

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

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

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

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

【讨论】:

这不涉及双精度/浮点数。 Convert.ToDouble(String) 和 Convert.ToFloat(String) 当然可以。它们已经被 MSDN 实现了。 我将您的“作为转换事物的机制”解释为上面的代码也可用于转换双精度和浮点数。如果您的代码是部分解决问题的示例,而其他代码(例如 double/float)所需的其他代码,则我的上述评论不适用。【参考方案8】:

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

溢出异常 s 表示小于 MinValue 或大于 MaxValue 的数字。

【讨论】:

@It'sNotALie。一般来说,我会避免使用它们进行这种操作,但在这种情况下,写一个替换并不是直接的。如果您涉及IFormatProvider,则更是如此。

以上是关于判断字符串到 double/float/int/short/byte 是不是超出范围的主要内容,如果未能解决你的问题,请参考以下文章

Java怎么判断判断某个字段中汉字的长度在2到20内

判断回文字符串

用Shell编程,判断文件是否字符设备文件,如果是将其拷贝到/dev目录下

用While MSComm1.InBufferCount = 0只能判断接收到字符,不能判断接收是不是完毕,如何更改这条语句?

Java实验--关于简单字符串回文的递归判断实验

怎样判断一个字符是否汉字呢??