I'm using the BigRational
beta off the BCL CodePlex (bcl.codeplex.com), and I realized it had no parsing method, so I tried to write one. However, it's quite inefficient (5.5ms for a 254 character number). That's over 45x slower than the BigInteger implementation. I'd like to lower it to .5ms if that's even possible.
private static Regex DigitDotDigit = new Regex(@"^(\-|\+)?(\d+\.\d+)$", RegexOptions.Compiled);
private static Regex PlainDigit = new Regex(@"^(\-|\+)?\d+$", RegexOptions.Compiled);
private static Regex DigitSlashDigit = new Regex(@"^(\-|\+)?\d+/\d+$", RegexOptions.Compiled);
private static Regex DotDigit = new Regex(@"^(\-|\+)?(\.\d+)", RegexOptions.Compiled);
private static bool RegexInitiated = false;
public static bool TryParse(string parse, out BigRational result)
{
if (DigitDotDigit.IsMatch(parse))
{
int zeros;
bool isNegative = false;
string[] parts = parse.TrimStart('+').Split('.');
parts[1] = parts[1].TrimEnd('0');
if (parts[0].StartsWith("-"))
{
isNegative = true;
parts[0] = parts[0].Substring(1);
}
BigRational whole = new BigRational(BigInteger.Parse(parts[0]), BigInteger.Zero, BigInteger.One);
BigRational decimalPart = new BigRational(BigInteger.Parse(parts[1]), BigInteger.Zero, BigInteger.One);
zeros = parts[1].Length - parts[1].TrimStart('0').Length;
toSubtract = toSubtract + zeros;
if (zeros > 0)
{
toSubtract = toSubtract - 1;
}
while (toSubtract != 0)
{
decimalPart /= 10;
toSubtract = toSubtract - 1;
}
result = whole + decimalPart;
if (isNegative)
{
result = -result;
}
return true;
}
else if (DotDigit.IsMatch(parse))
{
return TryParse("0" + parse, out result);
}
else if (PlainDigit.IsMatch(parse))
{
parse = parse.TrimStart('+');
if (parse.StartsWith("-"))
{
result = new BigRational(-BigInteger.Parse(parse), BigInteger.Zero, BigInteger.One);
return true;
}
result = new BigRational(BigInteger.Parse(parse), BigInteger.Zero, BigInteger.One);
return true;
}
else if (DigitSlashDigit.IsMatch(parse))
{
string[] parts = parse.TrimStart('+').Split('/');
if (parts[0].StartsWith("-"))
{
parts[0] = parts[0].Substring(1);
result = -(new BigRational(BigInteger.Parse(parts[0]), BigInteger.Parse(parts[1])));
return true;
}
result = new BigRational(BigInteger.Parse(parts[0]), BigInteger.Parse(parts[1]));
return true;
}
result = BigInteger.Zero;
return false;
}
0.1
, or even just1
). And you should also include the whole method, so that we don't have to guess what the rest of it contains (even if it's quite obvious). \$\endgroup\$0.1001
. \$\endgroup\$