/// <summary> /// Writes a STON number literal to the text, representing a given content in scientific notation. /// A minimum precision can be provided, to determine how many digits must be written before the exponent. /// If the content is zero, it is written with an exponent of zero. /// </summary> /// <param name="content">The content to represent with the scientific notation number literal.</param> /// <param name="minPrecision"></param> public void WriteScientificNumberLiteral(string content, int minPrecision = 1) { CheckContentValidity(StonDataType.Number, content); // handling zero content if (content == "0") { if (minPrecision <= 1) { Write("0e0"); } else { Write($"0.{ new string('0', minPrecision-1) }e0"); } return; } var builder = new StringBuilder(); int eiof = content.IndexOf('e'); builder.Append(content.Remove(eiof)); // writing the significand part to the builder int offset = (content[0] == '-') ? 1 : 0; int precision = eiof - offset; if (minPrecision > precision) { builder.Append(new string('0', minPrecision - precision)); // adding trailing zeros to the required minimal precision } if (precision > 1 || minPrecision > 1) { builder.Insert(offset + 1, '.'); // if the number has more than 1 digit (including trailing zeros), decimal point is inserted } // writing the exponent, increased by the number of significant digits after the decimal point builder.Append('e'); builder.Append(NumericStringCalculator.Add(content.Substring(eiof + 1), precision - 1)); Write(builder.ToString()); }
/// <summary> /// Reads a content string from a number literal and passes the content. /// It is assumed that the possible minus sign was read earlier. /// After that, advances the reader to the next significant character. /// </summary> /// <param name="minus">Whether the number value is negative or not.</param> /// <returns>The content string of the number literal.</returns> public string ReadNumberContent(bool minus) { var significandBuilder = new StringBuilder(); if (minus) { significandBuilder.Append('-'); } int postDecimalCount = 0; // tracks how many digits follow the decimal point int trailingZerosCount = -1; // tracks how many zeros follow the last non-zero digit before the exponent // reading the significand digits before the decimal point while (Peek().HasChartype(StonChartype.Digit)) { ReadSignificandDigit(significandBuilder, ref trailingZerosCount); } if (TryAndSkip(StonChartype.DecimalPoint)) { // at least one digit must follow the decimal point if (!Peek().HasChartype(StonChartype.Digit)) { throw MakeUnexpectedCharacterException(StonChartype.Digit); } // reading the significand digits after the decimal point while (Peek().HasChartype(StonChartype.Digit)) { ++postDecimalCount; ReadSignificandDigit(significandBuilder, ref trailingZerosCount); } } // the significand is zero point zero if (significandBuilder.Length == (minus ? 1 : 0)) { // with significand being zero, exponent doesn't matter anymore // but still must be read so that it's not mistaken for another token if (TryAndSkip(StonChartype.Exponent)) { TryAndSkip(StonChartype.Sign); if (!Peek().HasChartype(StonChartype.Digit)) { throw MakeUnexpectedCharacterException(StonChartype.Digit); } while (TryAndSkip(StonChartype.Digit)) { } } return("0"); } // the number subtracted from the exponent // based on the digits after the decimal point, as well as the trailing zeros int exponentDiff = postDecimalCount - trailingZerosCount; // reading the exponent if (TryAndSkip(StonChartype.Exponent)) { var exponentBuilder = new StringBuilder(); if (Peek().HasChartype(StonChartype.Sign)) { if (ReadAndSkip() == '-') { exponentBuilder.Append('-'); } } // the exponent must have at least one digit if (!Peek().HasChartype(StonChartype.Digit)) { throw MakeUnexpectedCharacterException(StonChartype.Digit); } // skipping the leading zeros while (TryAndSkip(StonChartype.ZeroDigit)) { } // adding the subsequent exponent digits, including the last zeros while (Peek().HasChartype(StonChartype.Digit)) { exponentBuilder.Append((char)ReadAndSkip()); } // if declared exponent is non-zero, the exponent is calculated as a numeric string difference if (exponentBuilder.Length > 0 && (exponentBuilder.Length > 1 || exponentBuilder[0] != '-')) { return(significandBuilder.ToString() + "e" + NumericStringCalculator.Subtract(exponentBuilder.ToString(), exponentDiff)); } } // the exponent was omitted or declared as zero return(significandBuilder.ToString() + "e" + (-exponentDiff).ToString()); }