Skip to main content
added 30 characters in body
Source Link
Heslacher
  • 51k
  • 5
  • 83
  • 177
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0');

    }

    if (result < 0)
        {
             result = 0;
             return false;
        }
    }

    

    if (isNegative) { result = -result; }

    return true;

}  
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0');

    }

    if (result < 0)
    {
        result = 0;
        return false;
    }

    if (isNegative) { result = -result; }

    return true;

}  
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0');

        if (result < 0)
        {
             result = 0;
             return false;
        }
    }

    

    if (isNegative) { result = -result; }

    return true;

}  
deleted 18 characters in body
Source Link
Heslacher
  • 51k
  • 5
  • 83
  • 177
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0'); 

    }

    if (result < 0)
        {
            result = 0;
            return false;
        }

    }

    if (isNegative) { result = -result; }

    return true;

}  
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0');
        if (result < 0)
        {
            result = 0;
            return false;
        }

    }

    if (isNegative) { result = -result; }

    return true;

}  
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0'); 

    }

    if (result < 0)
    {
        result = 0;
        return false;
    }

    if (isNegative) { result = -result; }

    return true;

}  
added 1622 characters in body
Source Link
Heslacher
  • 51k
  • 5
  • 83
  • 177
private const char CharNegative = '-';
private const int possibleMaxLength = 10;
private const int possibleMaxNegativeLength = 11;
private static string comparePositive = int.MaxValue.ToString();
private static string compareNegative =int.MinValue.ToString();
public static bool FastTryParseIntOld2FastTryParseInt(string input, out int result)
{
    result = 0;
    if (string.IsNullOrWhiteSpace(input)) { return false; }

    int length = input.Length;

    bool isNegative = false;
    int currentIndex = 0;
    
    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }
    else if (length < maxLength)
    {
        char nextChar;
        while (currentIndex < length)
        {
            nextChar = input[currentIndex++];
            if (nextChar < '0' || nextChar > '9')
            {
                result = 0;
                return false;
            }
            result = result * 10 + (nextChar - '0');

        }
    }
    else
    {
        bool needsToBeCompared = true;
        string valueToCompare = isNegative ? compareNegative : comparePositive;
        char nextChar;
        char compareChar;
        while (currentIndex < maxLength)
        {
            nextChar = input[currentIndex];
            compareChar = valueToCompare[currentIndex];

            if (nextChar < '0' || nextChar > '9' || (needsToBeCompared && compareChar < nextChar))
            {
                result = 0;
                return false;
            }

            if (needsToBeCompared)
            {
                needsToBeCompared = compareChar == nextChar;
            }

            result = result * 10 + (nextChar - '0');
            currentIndex++;
        }
    }

    if (isNegative) { result = -result; }

    return true;
}
private static Random random = new Random();

private static IEnumerable<string> GenerateRandomInput(int iterations)
{
    if (iterations == 0) yield break;

    for (int i = 0; i < iterations; i++)
    {
        if (i % 2 == 0)
        {
            yield return LongRandom((long)int.MinValue, ((long)int.MaxValue)).ToString();
        }
        else if (i % 3 == 0)
        {
            yield return LongRandom((long)int.MaxValue, ((long)int.MaxValue + 10000)).ToString();
        }
        else
        {
            yield return LongRandom(long.MinValue, long.MaxValue).ToString().Insert(3, "a");                    
        }
    }
}

private static long LongRandom(long min, long max)
{
    byte[] buf = new byte[8];
    random.NextBytes(buf);
    long longRand = BitConverter.ToInt64(buf, 0);

    return (Math.Abs(longRand % (max - min)) + min);
}  

Edit
Since you don't bother about special cases like null being passed to the method and performance is your target, I have changed it like so

public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0');
        if (result < 0)
        {
            result = 0;
            return false;
        }

    }

    if (isNegative) { result = -result; }

    return true;

}  

If int result is overflowing it becomes negative so we just check if result < 0 to return false.

This runs in 2065 ms vs int.TryParse in 11220 ms.

Btw. you only need the unchecked keyword if you have checked "Check for arithmetic overflow/underflow" in the advanced build settings.

private const char CharNegative = '-';
private const int possibleMaxLength = 10;
private const int possibleMaxNegativeLength = 11;
private static string comparePositive = int.MaxValue.ToString();
private static string compareNegative =int.MinValue.ToString();
public static bool FastTryParseIntOld2(string input, out int result)
{
    result = 0;
    if (string.IsNullOrWhiteSpace(input)) { return false; }

    int length = input.Length;

    bool isNegative = false;
    int currentIndex = 0;
    
    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }
    else if (length < maxLength)
    {
        char nextChar;
        while (currentIndex < length)
        {
            nextChar = input[currentIndex++];
            if (nextChar < '0' || nextChar > '9')
            {
                result = 0;
                return false;
            }
            result = result * 10 + (nextChar - '0');

        }
    }
    else
    {
        bool needsToBeCompared = true;
        string valueToCompare = isNegative ? compareNegative : comparePositive;
        char nextChar;
        char compareChar;
        while (currentIndex < maxLength)
        {
            nextChar = input[currentIndex];
            compareChar = valueToCompare[currentIndex];

            if (nextChar < '0' || nextChar > '9' || (needsToBeCompared && compareChar < nextChar))
            {
                result = 0;
                return false;
            }

            if (needsToBeCompared)
            {
                needsToBeCompared = compareChar == nextChar;
            }

            result = result * 10 + (nextChar - '0');
            currentIndex++;
        }
    }

    if (isNegative) { result = -result; }

    return true;
}
private static Random random = new Random();

private static IEnumerable<string> GenerateRandomInput(int iterations)
{
    if (iterations == 0) yield break;

    for (int i = 0; i < iterations; i++)
    {
        if (i % 2 == 0)
        {
            yield return LongRandom((long)int.MinValue, ((long)int.MaxValue)).ToString();
        }
        else if (i % 3 == 0)
        {
            yield return LongRandom((long)int.MaxValue, ((long)int.MaxValue + 10000)).ToString();
        }
        else
        {
            yield return LongRandom(long.MinValue, long.MaxValue).ToString().Insert(3, "a");                    
        }
    }
}

private static long LongRandom(long min, long max)
{
    byte[] buf = new byte[8];
    random.NextBytes(buf);
    long longRand = BitConverter.ToInt64(buf, 0);

    return (Math.Abs(longRand % (max - min)) + min);
}  
private const char CharNegative = '-';
private const int possibleMaxLength = 10;
private const int possibleMaxNegativeLength = 11;
private static string comparePositive = int.MaxValue.ToString();
private static string compareNegative =int.MinValue.ToString();
public static bool FastTryParseInt(string input, out int result)
{
    result = 0;
    if (string.IsNullOrWhiteSpace(input)) { return false; }

    int length = input.Length;

    bool isNegative = false;
    int currentIndex = 0;
    
    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }
    else if (length < maxLength)
    {
        char nextChar;
        while (currentIndex < length)
        {
            nextChar = input[currentIndex++];
            if (nextChar < '0' || nextChar > '9')
            {
                result = 0;
                return false;
            }
            result = result * 10 + (nextChar - '0');

        }
    }
    else
    {
        bool needsToBeCompared = true;
        string valueToCompare = isNegative ? compareNegative : comparePositive;
        char nextChar;
        char compareChar;
        while (currentIndex < maxLength)
        {
            nextChar = input[currentIndex];
            compareChar = valueToCompare[currentIndex];

            if (nextChar < '0' || nextChar > '9' || (needsToBeCompared && compareChar < nextChar))
            {
                result = 0;
                return false;
            }

            if (needsToBeCompared)
            {
                needsToBeCompared = compareChar == nextChar;
            }

            result = result * 10 + (nextChar - '0');
            currentIndex++;
        }
    }

    if (isNegative) { result = -result; }

    return true;
}
private static Random random = new Random();

private static IEnumerable<string> GenerateRandomInput(int iterations)
{
    if (iterations == 0) yield break;

    for (int i = 0; i < iterations; i++)
    {
        if (i % 2 == 0)
        {
            yield return LongRandom((long)int.MinValue, ((long)int.MaxValue)).ToString();
        }
        else if (i % 3 == 0)
        {
            yield return LongRandom((long)int.MaxValue, ((long)int.MaxValue + 10000)).ToString();
        }
        else
        {
            yield return LongRandom(long.MinValue, long.MaxValue).ToString().Insert(3, "a");                    
        }
    }
}

private static long LongRandom(long min, long max)
{
    byte[] buf = new byte[8];
    random.NextBytes(buf);
    long longRand = BitConverter.ToInt64(buf, 0);

    return (Math.Abs(longRand % (max - min)) + min);
}  

Edit
Since you don't bother about special cases like null being passed to the method and performance is your target, I have changed it like so

public static bool FastTryParseInt(string input, out int result)
{
    result = 0;

    int length = input.Length;
    if (length == 0) { return false; }

    bool isNegative = false;
    int currentIndex = 0;

    if (input[0] == CharNegative)
    {
        if (length > possibleMaxNegativeLength) { return false; }
        isNegative = true;
        ++currentIndex;
    }

    int maxLength = isNegative ? possibleMaxNegativeLength : possibleMaxLength;

    if (length > maxLength)
    {
        return false;
    }

    char nextChar;
    while (currentIndex < length)
    {
        nextChar = input[currentIndex++];

        if (nextChar < '0' || nextChar > '9')
        {
            result = 0;
            return false;
        }

        result = result * 10 + (nextChar - '0');
        if (result < 0)
        {
            result = 0;
            return false;
        }

    }

    if (isNegative) { result = -result; }

    return true;

}  

If int result is overflowing it becomes negative so we just check if result < 0 to return false.

This runs in 2065 ms vs int.TryParse in 11220 ms.

Btw. you only need the unchecked keyword if you have checked "Check for arithmetic overflow/underflow" in the advanced build settings.

Source Link
Heslacher
  • 51k
  • 5
  • 83
  • 177
Loading