Esempio n. 1
0
        /// <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());
        }
Esempio n. 2
0
        /// <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());
        }