Example #1
0
        public static FastInteger[] DecimalDigitLengthBounds(EInteger ei)
        {
            long longBitLength = ei.GetUnsignedBitLengthAsInt64();

            if (longBitLength < 33)
            {
                // Can easily be calculated without estimation
                var fi = new FastInteger((int)ei.GetDigitCountAsInt64());
                return(new FastInteger[] { fi, fi });
            }
            else if (longBitLength <= 2135)
            {
                var bitlen    = (int)longBitLength;
                int minDigits = 1 + (((bitlen - 1) * 631305) >> 21);
                int maxDigits = 1 + ((bitlen * 631305) >> 21);
                if (minDigits == maxDigits)
                {
                    var fi = new FastInteger(minDigits);
                    return(new FastInteger[] { fi, fi });
                }
                else
                {
                    return(new FastInteger[] {
                        new FastInteger(minDigits), // lower bound
                        new FastInteger(maxDigits), // upper bound
                    });
                }
            }
            else if (longBitLength <= 6432162)
            {
                var bitlen = (int)longBitLength;
                // Approximation of ln(2)/ln(10)
                int minDigits = 1 + (int)(((long)(bitlen - 1) * 661971961083L) >> 41);
                int maxDigits = 1 + (int)(((long)bitlen * 661971961083L) >> 41);
                if (minDigits == maxDigits)
                {
                    var fi = new FastInteger(minDigits);
                    return(new FastInteger[] { fi, fi });
                }
                else
                {
                    return(new FastInteger[] {
                        new FastInteger(minDigits), // lower bound
                        new FastInteger(maxDigits), // upper bound
                    });
                }
            }
            else
            {
                // Bit length is big enough that these bounds will
                // overestimate or underestimate the true base-10 digit length
                // as appropriate.
                EInteger bigBitLength = ei.GetUnsignedBitLengthAsEInteger();
                EInteger lowerBound   = bigBitLength.Multiply(100).Divide(335);
                EInteger upperBound   = bigBitLength.Divide(3);
                return(new FastInteger[] {
                    FastInteger.FromBig(lowerBound), // lower bound
                    FastInteger.FromBig(upperBound), // upper bound
                });
            }
        }