/// <summary> /// Parse a part (real or complex) from a complex number. /// </summary> /// <param name="token">Start Token.</param> /// <param name="imaginary">Is set to <c>true</c> if the part identified itself as being imaginary.</param> /// <param name="format"> /// An <see cref="IFormatProvider"/> that supplies culture-specific /// formatting information. /// </param> /// <returns>Resulting part as double.</returns> /// <exception cref="FormatException"/> private static double ParsePart(ref LinkedListNode <string> token, out bool imaginary, IFormatProvider format) { imaginary = false; if (token == null) { throw new FormatException(); } // handle prefix modifiers if (token.Value == "+") { token = token.Next; if (token == null) { throw new FormatException(); } } var negative = false; if (token.Value == "-") { negative = true; token = token.Next; if (token == null) { throw new FormatException(); } } // handle prefix imaginary symbol if (String.Compare(token.Value, "i", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(token.Value, "j", StringComparison.OrdinalIgnoreCase) == 0) { imaginary = true; token = token.Next; if (token == null) { return(negative ? -1 : 1); } } #if SILVERLIGHT var value = GlobalizationHelper.ParseDouble(ref token); #else var value = GlobalizationHelper.ParseDouble(ref token, format.GetCultureInfo()); #endif // handle suffix imaginary symbol if (token != null && (String.Compare(token.Value, "i", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(token.Value, "j", StringComparison.OrdinalIgnoreCase) == 0)) { if (imaginary) { // only one time allowed: either prefix or suffix, or neither. throw new FormatException(); } imaginary = true; token = token.Next; } return(negative ? -value : value); }
/// <summary> /// Creates a complex number based on a string. The string can be in the /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. /// </summary> /// <returns> /// A complex number containing the value specified by the given string. /// </returns> /// <param name="value"> /// the string to parse. /// </param> /// <param name="formatProvider"> /// An <see cref="IFormatProvider"/> that supplies culture-specific /// formatting information. /// </param> public static Complex ToComplex(this string value, IFormatProvider formatProvider) { if (value == null) { throw new ArgumentNullException(value); } value = value.Trim(); if (value.Length == 0) { throw new FormatException(); } // strip out parens if (value.StartsWith("(", StringComparison.Ordinal)) { if (!value.EndsWith(")", StringComparison.Ordinal)) { throw new FormatException(); } value = value.Substring(1, value.Length - 2).Trim(); } // keywords var numberFormatInfo = formatProvider.GetNumberFormatInfo(); var textInfo = formatProvider.GetTextInfo(); var keywords = new[] { textInfo.ListSeparator, numberFormatInfo.NaNSymbol, numberFormatInfo.NegativeInfinitySymbol, numberFormatInfo.PositiveInfinitySymbol, "+", "-", "i", "j" }; // lexing var tokens = new LinkedList <string>(); GlobalizationHelper.Tokenize(tokens.AddFirst(value), keywords, 0); var token = tokens.First; // parse the left part bool isLeftPartImaginary; var leftPart = ParsePart(ref token, out isLeftPartImaginary, formatProvider); if (token == null) { return(isLeftPartImaginary ? new Complex(0, leftPart) : new Complex(leftPart, 0)); } // parse the right part if (token.Value == textInfo.ListSeparator) { // format: real,imag token = token.Next; if (isLeftPartImaginary) { // left must not contain 'i', right doesn't matter. throw new FormatException(); } bool isRightPartImaginary; var rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider); return(new Complex(leftPart, rightPart)); } else { // format: real + imag bool isRightPartImaginary; var rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider); if (!(isLeftPartImaginary ^ isRightPartImaginary)) { // either left or right part must contain 'i', but not both. throw new FormatException(); } return(isLeftPartImaginary ? new Complex(rightPart, leftPart) : new Complex(leftPart, rightPart)); } }