예제 #1
0
        public long ToInt64(NumberInfo numberInfo)
        {
            if (numberInfo.radix != radix)
            {
                throw new FormatException("radix");
            }

            ulong uInt64 = ToUInt64(numberInfo);

            if (numberInfo.isNegative)
            {
                if (uInt64 > PositiveInt64MinValue)
                {
                    throw new OverflowException("Number out of Int64 range.");
                }

                if (uInt64 == PositiveInt64MinValue)
                {
                    return(long.MinValue);
                }

                return(-(long)uInt64);
            }

            if (uInt64 > Int64MaxValue)
            {
                throw new OverflowException("Number out of Int64 range.");
            }

            return((long)uInt64);
        }
예제 #2
0
        public static decimal ToDecimal(NumberInfo numberInfo)
        {
            if (numberInfo.radix != DecimalRadix)
            {
                throw new FormatException("decimal radix.");
            }

            if (numberInfo.exponentCount > 5)
            {
                throw new OverflowException("Exponent too big.");
            }

            if (numberInfo.integerCount + numberInfo.fractionalCount > DecimalMaxScale + 2)
            {
                throw new OverflowException("Number out of Decimal range.");
            }

            var decimalInstance = Decimal;

            var exponent = decimalInstance.UncheckedParse(numberInfo.chars + numberInfo.exponentBegin, numberInfo.exponentCount);

            if (numberInfo.exponentIsNegative)
            {
                exponent = -exponent;
            }

            var number       = stackalloc uint[5];
            var numberLength = 0;

            ToDecimalNumber(numberInfo.chars + numberInfo.integerBegin, numberInfo.integerCount, number, ref numberLength);

            ToDecimalNumber(numberInfo.chars + numberInfo.fractionalBegin, numberInfo.fractionalCount, number, ref numberLength);

            var scale = numberInfo.fractionalCount - exponent;

            if (scale < 0)
            {
                scale = -scale;

                if (scale > DecimalMaxScale - (numberInfo.integerCount + numberInfo.fractionalCount))
                {
                    throw new OverflowException("Exponent too big.");
                }

                while (scale > 0)
                {
                    Mult(number, numberLength, DecimalRadix, out uint carry);

                    if (carry != 0)
                    {
                        number[numberLength] = carry;

                        ++numberLength;
                    }

                    --scale;
                }
            }

            if (numberLength > 3)
            {
                throw new OverflowException("Number out of Decimal range.");
            }

            decimal r;

            var upValue = (uint *)(&r);

            upValue[2] = number[0];
            upValue[3] = number[1];
            upValue[1] = number[2];

            if (numberInfo.isNegative)
            {
                upValue[0] = SignMask;
            }

            if (scale != 0)
            {
                if (scale > DecimalMaxScale)
                {
                    throw new OverflowException("Scale too big.");
                }

                ((byte *)upValue)[2] = (byte)scale;
            }

            return(r);
        }
예제 #3
0
        public NumberInfo GetNumberInfo(char *chars, int length)
        {
            var r = new NumberInfo();

            r.chars = chars;
            r.radix = radix;

            if (length > 0)
            {
                var index = 0;

                var signChar = chars[0];

                switch (signChar)
                {
                case NegativeSign:
                case PositiveSign:
                    ++index;
                    r.isNegative = signChar == NegativeSign;
                    break;
                }

                var beforeZeroCount = 0;

                while (index < length && chars[index] == DigitalsZeroValue)
                {
                    ++beforeZeroCount;
                    ++index;
                }

                var integerBegin = index;
                var integerCount = 0;

                while (index < length && ToRadix(chars[index]) < radix)
                {
                    ++integerCount;
                    ++index;
                }

                if (integerCount != 0)
                {
                    r.integerBegin = integerBegin;
                    r.integerCount = integerCount;
                }
                else if (beforeZeroCount != 0)
                {
                    r.integerBegin = index - 1;
                    r.integerCount = 1;
                }

                if (index < length && chars[index] == DotSign)
                {
                    r.isFloat = true;

                    ++index;

                    var fractionalBegin = index;
                    var fractionalCount = 0;

                    while (index < length && ToRadix(chars[index]) < radix)
                    {
                        ++fractionalCount;
                        ++index;
                    }

                    if (fractionalCount != 0)
                    {
                        for (int fractionalRight = fractionalBegin + fractionalCount - 1; fractionalRight >= 0; --fractionalRight)
                        {
                            if (chars[fractionalRight] != DigitalsZeroValue)
                            {
                                break;
                            }

                            --fractionalCount;
                        }

                        r.haveFractional  = fractionalCount != 0;
                        r.fractionalBegin = fractionalBegin;
                        r.fractionalCount = fractionalCount;
                    }
                }

                if (index < length)
                {
                    bool haveExponent = false;

                    switch (chars[index])
                    {
                    case exponentSign:
                    case ExponentSign:

                        ++index;

                        haveExponent = true;

                        break;
                    }

                    if (haveExponent && index < length)
                    {
                        var exponentSignChar = chars[index];

                        switch (exponentSignChar)
                        {
                        case NegativeSign:
                        case PositiveSign:
                            ++index;
                            r.exponentIsNegative = exponentSignChar == NegativeSign;
                            break;
                        }

                        var exponentBegin = index;

                        var exponentBeforeZeroCount = 0;

                        while (index < length && chars[index] == DigitalsZeroValue)
                        {
                            ++exponentBeforeZeroCount;
                            ++index;
                        }

                        var exponentCount = 0;

                        while (index < length && ToRadix(chars[index]) < radix)
                        {
                            ++exponentCount;
                            ++index;
                        }

                        if (exponentCount != 0)
                        {
                            r.exponentBegin = exponentBegin;
                            r.exponentCount = exponentCount;
                        }
                        else if (beforeZeroCount != 0)
                        {
                            r.exponentBegin = index - 1;
                            r.exponentCount = 1;
                        }
                    }
                }

                r.end = index;
            }

            return(r);
        }
예제 #4
0
        public double ToDouble(NumberInfo numberInfo)
        {
            if (numberInfo.radix != radix)
            {
                throw new FormatException("radix");
            }

            if (numberInfo.exponentCount > 5)
            {
                throw new OverflowException("Exponent too big.");
            }

            var exponent = UncheckedParse(numberInfo.chars + numberInfo.exponentBegin, numberInfo.exponentCount);

            if (numberInfo.exponentIsNegative)
            {
                exponent = -exponent;
            }

            var r = 0D;

            for (int i = 0, j = numberInfo.integerBegin; i < numberInfo.integerCount; ++i, ++j)
            {
                r = r * radix + ToRadix(numberInfo.chars[j]);
            }

            for (int i = 0, j = numberInfo.fractionalBegin; i < numberInfo.fractionalCount; ++i, ++j)
            {
                r = r * radix + ToRadix(numberInfo.chars[j]);
            }

            var e = (int)exponent - numberInfo.fractionalCount;

            var exponents = positiveExponents;

            if (e < 0)
            {
                exponents = negativeExponents;

                e = -e;
            }

            if (e > 0)
            {
                while (e >= 100)
                {
                    r *= exponents[100];

                    e -= 100;
                }

                while (e >= 10)
                {
                    r *= exponents[10];

                    e -= 10;
                }

                while (e >= 1)
                {
                    r *= exponents[1];

                    --e;
                }
            }

            if (r > DoubleMaxPositive)
            {
                throw new OverflowException("Number out of Double range.");
            }

            return(r);
        }
예제 #5
0
        public ulong ToUInt64(NumberInfo numberInfo)
        {
            if (numberInfo.radix != radix)
            {
                throw new FormatException("radix");
            }

            if (numberInfo.exponentCount > 5)
            {
                throw new OverflowException("Exponent too big.");
            }

            var exponent = UncheckedParse(numberInfo.chars + numberInfo.exponentBegin, numberInfo.exponentCount);

            if (numberInfo.exponentIsNegative)
            {
                exponent = -exponent;
            }

            int count = ((int)exponent) + numberInfo.integerCount;

            if (count > uInt64NumbersLength)
            {
                throw new OverflowException("Number out of UInt64 range.");
            }

            if (count <= 0)
            {
                return(0);
            }

            byte l = 0;
            var  c = count;
            var  r = 0UL;

            for (int i = 0, j = numberInfo.integerBegin; i < numberInfo.integerCount; ++i, ++j, --c)
            {
                l = ToRadix(numberInfo.chars[j]);

                if (c <= 1)
                {
                    goto End;
                }

                r = r * radix + l;
            }

            for (int i = 0, j = numberInfo.fractionalBegin; i < numberInfo.fractionalCount; ++i, ++j, --c)
            {
                l = ToRadix(numberInfo.chars[j]);

                if (c <= 1)
                {
                    goto End;
                }

                r = r * radix + l;
            }

            for (; c > 1; --c)
            {
                r = r * radix;
            }

End:

            if (count == uInt64NumbersLength && r > (UInt64MaxValue - l) / radix)
            {
                throw new OverflowException("Number out of UInt64 range.");
            }

            r = r * radix + l;

            return(r);
        }
        public NumberInfo GetNumberInfo(char *chars, int length)
        {
            var number = new NumberInfo
            {
                integerBegin    = -1,
                fractionalBegin = -1,
                exponentBegin   = -1,

                chars = chars,
                radix = radix
            };

            if (length > 0)
            {
                var index = 0;

                var signChar = chars[0];

                switch (signChar)
                {
                case NegativeSign:
                case PositiveSign:
                    ++index;
                    number.isNegative = signChar == NegativeSign;
                    break;
                }

                var integerBegin      = index;
                var integerCount      = 0;
                var integerSplitCount = 0;

                GetNumberCount(chars, length, ref index, ref integerCount, ref integerSplitCount);

                if (integerCount != 0)
                {
                    SubBeginingZeroOrSplitAndEndingSplit(chars, ref integerBegin, ref integerCount, ref integerSplitCount);

                    number.integerBegin      = integerBegin;
                    number.integerCount      = integerCount;
                    number.integerSplitCount = integerSplitCount;
                }

                if (index < length && chars[index] == DotSign)
                {
                    number.isFloat = true;

                    ++index;

                    var fractionalBegin      = index;
                    var fractionalCount      = 0;
                    var fractionalSplitCount = 0;

                    GetNumberCount(chars, length, ref index, ref fractionalCount, ref fractionalSplitCount);

                    if (fractionalCount != 0)
                    {
                        SubBeginingSplitAndEndingZeroOrSplit(chars, ref integerBegin, ref integerCount, ref integerSplitCount);

                        number.haveFractional       = fractionalCount != 0;
                        number.fractionalBegin      = fractionalBegin;
                        number.fractionalCount      = fractionalCount;
                        number.fractionalSplitCount = fractionalSplitCount;
                    }
                }

                if (index < length)
                {
                    bool haveExponent = false;

                    switch (chars[index])
                    {
                    case exponentSign:
                    case ExponentSign:

                        ++index;

                        haveExponent = true;

                        break;

                    case PositiveSign:
                    case NegativeSign:
                        switch (chars[index - 1])
                        {
                        case exponentSign:
                        case ExponentSign:
                            if (number.isFloat)
                            {
                                if (number.fractionalCount >= 2)
                                {
                                    --number.fractionalCount;

                                    haveExponent = true;
                                }
                            }
                            else if (number.integerCount >= 2)
                            {
                                --number.integerCount;

                                haveExponent = true;
                            }
                            break;
                        }
                        break;
                    }

                    if (haveExponent && index < length)
                    {
                        var exponentSignChar = chars[index];

                        switch (exponentSignChar)
                        {
                        case NegativeSign:
                        case PositiveSign:
                            ++index;
                            number.exponentIsNegative = exponentSignChar == NegativeSign;
                            break;
                        }

                        var exponentBegin      = index;
                        var exponentCount      = 0;
                        var exponentSplitCount = 0;

                        GetNumberCount(chars, length, ref index, ref exponentCount, ref exponentSplitCount);

                        if (exponentCount != 0)
                        {
                            SubBeginingZeroOrSplitAndEndingSplit(chars, ref exponentBegin, ref exponentCount, ref exponentSplitCount);

                            number.exponentBegin      = exponentBegin;
                            number.exponentCount      = exponentCount;
                            number.exponentSplitCount = exponentSplitCount;
                        }
                    }
                }

                number.end = index;
            }

            return(number);
        }