예제 #1
0
        /// <summary>
        /// Returns the digits for the format spec, no sign is included.
        /// </summary>
        private static string DoubleToFormatString(CodeContext/*!*/ context, double self, StringFormatSpec/*!*/ spec) {
            self = Math.Abs(self);
            const int DefaultPrecision = 6;
            int precision = spec.Precision ?? DefaultPrecision;

            string digits;
            switch (spec.Type) {
                case '%': digits = self.ToString("0." + new string('0', precision) + "%", CultureInfo.InvariantCulture); break;
                case 'f':
                case 'F': digits = self.ToString("0." + new string('0', precision), CultureInfo.InvariantCulture); break;
                case 'e': digits = self.ToString("0." + new string('0', precision) + "e+00", CultureInfo.InvariantCulture); break;
                case 'E': digits = self.ToString("0." + new string('0', precision) + "E+00", CultureInfo.InvariantCulture); break;
                case '\0':
                case null:
                    if (spec.Precision != null) {
                        // precision applies to the combined digits before and after the decimal point
                        // so we first need find out how many digits we have before...
                        int digitCnt = 1;
                        double cur = self;
                        while (cur >= 10) {
                            cur /= 10;
                            digitCnt++;
                        }

                        // Use exponents if we don't have enough room for all the digits before.  If we
                        // only have as single digit avoid exponents.
                        if (digitCnt > spec.Precision.Value && digitCnt != 1) {
                            // first round off the decimal value
                            self = MathUtils.RoundAwayFromZero(self, 0);

                            // then remove any insignificant digits
                            double pow = Math.Pow(10, digitCnt - Math.Max(spec.Precision.Value, 1));
                            self = self - (self % pow);

                            // finally format w/ the requested precision
                            string fmt = "0.0" + new string('#', spec.Precision.Value);

                            digits = self.ToString(fmt + "e+00", CultureInfo.InvariantCulture);
                        } else {
                            // we're including all the numbers to the right of the decimal we can, we explicitly 
                            // round to match CPython's behavior
                            int decimalPoints = Math.Max(spec.Precision.Value - digitCnt, 0);

                            self = MathUtils.RoundAwayFromZero(self, decimalPoints);
                            digits = self.ToString("0.0" + new string('#', decimalPoints));
                        }
                    } else {
                        // just the default formatting
                        if (IncludeExponent(self)) {
                            digits = self.ToString("0.#e+00", CultureInfo.InvariantCulture);
                        } else {
                            digits = self.ToString("0.0###", CultureInfo.InvariantCulture);
                        }
                    }
                    break;
                case 'n':
                case 'g':
                case 'G': {
                        // precision applies to the combined digits before and after the decimal point
                        // so we first need find out how many digits we have before...
                        int digitCnt = 1;
                        double cur = self;
                        while (cur >= 10) {
                            cur /= 10;
                            digitCnt++;
                        }

                        // Use exponents if we don't have enough room for all the digits before.  If we
                        // only have as single digit avoid exponents.
                        if (digitCnt > precision && digitCnt != 1) {
                            // first round off the decimal value
                            self = MathUtils.RoundAwayFromZero(self, 0);

                            // then remove any insignificant digits
                            double pow = Math.Pow(10, digitCnt - Math.Max(precision, 1));
                            double rest = self / pow;
                            self = self - self % pow;
                            if ((rest % 1) >= .5) {
                                // round up
                                self += pow;
                            }

                            string fmt;
                            if (spec.Type == 'n' && PythonContext.GetContext(context).NumericCulture != PythonContext.CCulture) {
                                // we've already figured out, we don't have any digits for decimal points, so just format as a number + exponent
                                fmt = "0";
                            } else if (spec.Precision > 1 || digitCnt > 6) {
                                // include the requested percision to the right of the decimal
                                fmt = "0.#" + new string('#', precision);
                            } else {
                                // zero precision, no decimal
                                fmt = "0";
                            }

                            digits = self.ToString(fmt + (spec.Type == 'G' ? "E+00" : "e+00"), CultureInfo.InvariantCulture);
                        } else {
                            // we're including all the numbers to the right of the decimal we can, we explicitly 
                            // round to match CPython's behavior
                            if (self < 1) {
                                // no implicit 0
                                digitCnt--;
                            }
                            int decimalPoints = Math.Max(precision - digitCnt, 0);

                            self = MathUtils.RoundAwayFromZero(self, decimalPoints);

                            if (spec.Type == 'n' && PythonContext.GetContext(context).NumericCulture != PythonContext.CCulture) {
                                if (digitCnt != precision && (self % 1) != 0) {
                                    digits = self.ToString("#,0.0" + new string('#', decimalPoints));
                                } else {
                                    // leave out the decimal if the precision == # of digits or we have a whole number
                                    digits = self.ToString("#,0");
                                }
                            } else {
                                if (digitCnt != precision && (self % 1) != 0) {
                                    digits = self.ToString("0.0" + new string('#', decimalPoints));
                                } else {
                                    // leave out the decimal if the precision == # of digits or we have a whole number
                                    digits = self.ToString("0");
                                }
                            }
                        }
                    }
                    break;
                default:
                    throw PythonOps.ValueError("Unknown format code '{0}' for object of type 'float'", spec.Type.ToString());
            }

            return digits;
        }
예제 #2
0
        public static string /*!*/ __format__(CodeContext /*!*/ context, BigInteger /*!*/ self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            BigInteger val = self;

            if (self < 0)
            {
                val = -self;
            }
            string digits;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = context.LanguageContext.NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }

                digits = FormattingHelper.ToCultureString(val, context.LanguageContext.NumericCulture.NumberFormat, spec);
                break;

            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    var width = spec.Width ?? 0;
                    // If we're inserting commas, and we're padding with leading zeros.
                    // AlignNumericText won't know where to place the commas,
                    // so force .Net to help us out here.
                    if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1)
                    {
                        digits = val.ToString(FormattingHelper.ToCultureString(self, FormattingHelper.InvariantCommaNumberInfo, spec));
                    }
                    else
                    {
                        digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    digits = val.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    goto case 'd';
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    goto case 'd';
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'X':
                digits = AbsToHex(val, false);
                break;

            case 'x':
                digits = AbsToHex(val, true);
                break;

            case 'o':     // octal
                digits = ToOctal(val, true);
                break;

            case 'b':     // binary
                digits = ToBinary(val, false, true);
                break;

            case 'c':     // single char
                int iVal;
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }
                else if (!self.AsInt32(out iVal))
                {
                    throw PythonOps.OverflowError("long int too large to convert to int");
                }
                else if (iVal < 0 || iVal > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = ScriptingRuntimeHelpers.CharToString((char)iVal);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            Debug.Assert(digits[0] != '-');

            return(spec.AlignNumericText(digits, self.IsZero(), self.IsPositive()));
        }
예제 #3
0
        /// <summary>
        /// Returns the digits for the format spec, no sign is included.
        /// </summary>
        private static string DoubleToFormatString(CodeContext /*!*/ context, double self, StringFormatSpec /*!*/ spec)
        {
            self = Math.Abs(self);
            const int DefaultPrecision = 6;
            int       precision        = spec.Precision ?? DefaultPrecision;

            string digits;

            switch (spec.Type)
            {
            case '%': digits = self.ToString("0." + new string('0', precision) + "%", CultureInfo.InvariantCulture); break;

            case 'f':
            case 'F': digits = self.ToString("0." + new string('0', precision), CultureInfo.InvariantCulture); break;

            case 'e': digits = self.ToString("0." + new string('0', precision) + "e+00", CultureInfo.InvariantCulture); break;

            case 'E': digits = self.ToString("0." + new string('0', precision) + "E+00", CultureInfo.InvariantCulture); break;

            case '\0':
            case null:
                if (spec.Precision != null)
                {
                    // precision applies to the combined digits before and after the decimal point
                    // so we first need find out how many digits we have before...
                    int    digitCnt = 1;
                    double cur      = self;
                    while (cur >= 10)
                    {
                        cur /= 10;
                        digitCnt++;
                    }

                    // Use exponents if we don't have enough room for all the digits before.  If we
                    // only have as single digit avoid exponents.
                    if (digitCnt > spec.Precision.Value && digitCnt != 1)
                    {
                        // first round off the decimal value
                        self = MathUtils.RoundAwayFromZero(self, 0);

                        // then remove any insignificant digits
                        double pow = Math.Pow(10, digitCnt - Math.Max(spec.Precision.Value, 1));
                        self = self - (self % pow);

                        // finally format w/ the requested precision
                        string fmt = "0.0" + new string('#', spec.Precision.Value);

                        digits = self.ToString(fmt + "e+00", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        // we're including all the numbers to the right of the decimal we can, we explicitly
                        // round to match CPython's behavior
                        int decimalPoints = Math.Max(spec.Precision.Value - digitCnt, 0);

                        self   = MathUtils.RoundAwayFromZero(self, decimalPoints);
                        digits = self.ToString("0.0" + new string('#', decimalPoints));
                    }
                }
                else
                {
                    // just the default formatting
                    if (IncludeExponent(self))
                    {
                        digits = self.ToString("0.#e+00", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        digits = self.ToString("0.0###", CultureInfo.InvariantCulture);
                    }
                }
                break;

            case 'n':
            case 'g':
            case 'G': {
                // precision applies to the combined digits before and after the decimal point
                // so we first need find out how many digits we have before...
                int    digitCnt = 1;
                double cur      = self;
                while (cur >= 10)
                {
                    cur /= 10;
                    digitCnt++;
                }

                // Use exponents if we don't have enough room for all the digits before.  If we
                // only have as single digit avoid exponents.
                if (digitCnt > precision && digitCnt != 1)
                {
                    // first round off the decimal value
                    self = MathUtils.RoundAwayFromZero(self, 0);

                    // then remove any insignificant digits
                    double pow  = Math.Pow(10, digitCnt - Math.Max(precision, 1));
                    double rest = self / pow;
                    self = self - self % pow;
                    if ((rest % 1) >= .5)
                    {
                        // round up
                        self += pow;
                    }

                    string fmt;
                    if (spec.Type == 'n' && PythonContext.GetContext(context).NumericCulture != PythonContext.CCulture)
                    {
                        // we've already figured out, we don't have any digits for decimal points, so just format as a number + exponent
                        fmt = "0";
                    }
                    else if (spec.Precision > 1 || digitCnt > 6)
                    {
                        // include the requested percision to the right of the decimal
                        fmt = "0.#" + new string('#', precision);
                    }
                    else
                    {
                        // zero precision, no decimal
                        fmt = "0";
                    }

                    digits = self.ToString(fmt + (spec.Type == 'G' ? "E+00" : "e+00"), CultureInfo.InvariantCulture);
                }
                else
                {
                    // we're including all the numbers to the right of the decimal we can, we explicitly
                    // round to match CPython's behavior
                    if (self < 1)
                    {
                        // no implicit 0
                        digitCnt--;
                    }
                    int decimalPoints = Math.Max(precision - digitCnt, 0);

                    self = MathUtils.RoundAwayFromZero(self, decimalPoints);

                    if (spec.Type == 'n' && PythonContext.GetContext(context).NumericCulture != PythonContext.CCulture)
                    {
                        if (digitCnt != precision && (self % 1) != 0)
                        {
                            digits = self.ToString("#,0.0" + new string('#', decimalPoints));
                        }
                        else
                        {
                            // leave out the decimal if the precision == # of digits or we have a whole number
                            digits = self.ToString("#,0");
                        }
                    }
                    else
                    {
                        if (digitCnt != precision && (self % 1) != 0)
                        {
                            digits = self.ToString("0.0" + new string('#', decimalPoints));
                        }
                        else
                        {
                            // leave out the decimal if the precision == # of digits or we have a whole number
                            digits = self.ToString("0");
                        }
                    }
                }
            }
            break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}' for object of type 'float'", spec.Type.ToString());
            }

            return(digits);
        }
예제 #4
0
        public static string __format__(CodeContext /*!*/ context, int self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            string digits;
            int    width = 0;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = context.LanguageContext.NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }
                width = spec.Width ?? 0;

                // If we're padding with leading zeros and we might be inserting
                // culture sensitive number group separators. (i.e. commas)
                // So use FormattingHelper.ToCultureString for that support.
                if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1)
                {
                    digits = FormattingHelper.ToCultureString(self, culture.NumberFormat, spec);
                }
                else
                {
                    digits = self.ToString("N0", culture);
                }
                break;

            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    width = spec.Width ?? 0;

                    // If we're inserting commas, and we're padding with leading zeros.
                    // AlignNumericText won't know where to place the commas,
                    // so use FormattingHelper.ToCultureString for that support.
                    if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1)
                    {
                        digits = FormattingHelper.ToCultureString(self, FormattingHelper.InvariantCommaNumberInfo, spec);
                    }
                    else
                    {
                        digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    digits = self.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    // Handle the common case in 'd'.
                    goto case 'd';
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    // Handle the common case in 'd'.
                    goto case 'd';
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'X':
                digits = ToHex(self, false);
                break;

            case 'x':
                digits = ToHex(self, true);
                break;

            case 'o':     // octal
                digits = ToOctal(self, true);
                break;

            case 'b':     // binary
                digits = ToBinary(self, false);
                break;

            case 'c':     // single char
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }

                if (self < 0 || self > 0x10ffff)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x110000)");
                }

                digits = (self > char.MaxValue) ? char.ConvertFromUtf32(self) : ScriptingRuntimeHelpers.CharToString((char)self);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}' for object of type 'int'", spec.TypeRepr);
            }

            if (self < 0 && digits[0] == '-')
            {
                digits = digits.Substring(1);
            }

            return(spec.AlignNumericText(digits, self == 0, self > 0));
        }
예제 #5
0
        public static string /*!*/ __format__(CodeContext /*!*/ context, BigInteger /*!*/ self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            BigInteger val = self;

            if (self < 0)
            {
                val = -self;
            }
            string digits;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = PythonContext.GetContext(context).NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }

                digits = ToCultureString(val, PythonContext.GetContext(context).NumericCulture);
                break;

#if CLR2
            case null:
            case 'd':
                digits = val.ToString();
                break;

            case '%':
                if (val == BigInteger.Zero)
                {
                    digits = "0.000000%";
                }
                else
                {
                    digits = val.ToString() + "00.000000%";
                }
                break;

            case 'e': digits = ToExponent(val, true, 6, 7); break;

            case 'E': digits = ToExponent(val, false, 6, 7); break;

            case 'f':
                if (val != BigInteger.Zero)
                {
                    digits = val.ToString() + ".000000";
                }
                else
                {
                    digits = "0.000000";
                }
                break;

            case 'F':
                if (val != BigInteger.Zero)
                {
                    digits = val.ToString() + ".000000";
                }
                else
                {
                    digits = "0.000000";
                }
                break;

            case 'g':
                if (val >= 1000000)
                {
                    digits = ToExponent(val, true, 0, 6);
                }
                else
                {
                    digits = val.ToString();
                }
                break;

            case 'G':
                if (val >= 1000000)
                {
                    digits = ToExponent(val, false, 0, 6);
                }
                else
                {
                    digits = val.ToString();
                }
                break;
#else
            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (val >= 1000000)
                {
                    digits = val.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = val.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = val.ToString(CultureInfo.InvariantCulture);
                }
                break;
#endif
            case 'X':
                digits = AbsToHex(val, false);
                break;

            case 'x':
                digits = AbsToHex(val, true);
                break;

            case 'o':     // octal
                digits = ToOctal(val, true);
                break;

            case 'b':     // binary
                digits = ToBinary(val, false, true);
                break;

            case 'c':     // single char
                int iVal;
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }
                else if (!self.AsInt32(out iVal))
                {
                    throw PythonOps.OverflowError("long int too large to convert to int");
                }
                else if (iVal < 0 || iVal > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = digits = ScriptingRuntimeHelpers.CharToString((char)iVal);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            Debug.Assert(digits[0] != '-');

            return(spec.AlignNumericText(digits, self.IsZero(), self.IsPositive()));
        }
예제 #6
0
        public static string __format__(CodeContext /*!*/ context, int self, [NotNull] string /*!*/ formatSpec)
        {
            StringFormatSpec spec = StringFormatSpec.FromString(formatSpec);

            if (spec.Precision != null)
            {
                throw PythonOps.ValueError("Precision not allowed in integer format specifier");
            }

            string digits;

            switch (spec.Type)
            {
            case 'n':
                CultureInfo culture = PythonContext.GetContext(context).NumericCulture;

                if (culture == CultureInfo.InvariantCulture)
                {
                    // invariant culture maps to CPython's C culture, which doesn't
                    // include any formatting info.
                    goto case 'd';
                }

                digits = self.ToString("N0", PythonContext.GetContext(context).NumericCulture);
                break;

            case null:
            case 'd':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("D", CultureInfo.InvariantCulture);
                }
                break;

            case '%':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000%", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000%", CultureInfo.InvariantCulture);
                }
                break;

            case 'e':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000e+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'E':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("0.000000E+00", CultureInfo.InvariantCulture);
                }
                break;

            case 'f':
            case 'F':
                if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,########0.000000", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString("#########0.000000", CultureInfo.InvariantCulture);
                }
                break;

            case 'g':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####e+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'G':
                if (self >= 1000000 || self <= -1000000)
                {
                    digits = self.ToString("0.#####E+00", CultureInfo.InvariantCulture);
                }
                else if (spec.ThousandsComma)
                {
                    digits = self.ToString("#,0", CultureInfo.InvariantCulture);
                }
                else
                {
                    digits = self.ToString(CultureInfo.InvariantCulture);
                }
                break;

            case 'X':
                digits = ToHex(self, false);
                break;

            case 'x':
                digits = ToHex(self, true);
                break;

            case 'o':     // octal
                digits = ToOctal(self, true);
                break;

            case 'b':     // binary
                digits = ToBinary(self, false);
                break;

            case 'c':     // single char
                if (spec.Sign != null)
                {
                    throw PythonOps.ValueError("Sign not allowed with integer format specifier 'c'");
                }

                if (self < 0 || self > 0xFF)
                {
                    throw PythonOps.OverflowError("%c arg not in range(0x10000)");
                }

                digits = ScriptingRuntimeHelpers.CharToString((char)self);
                break;

            default:
                throw PythonOps.ValueError("Unknown format code '{0}'", spec.Type.ToString());
            }

            if (self < 0 && digits[0] == '-')
            {
                digits = digits.Substring(1);
            }

            return(spec.AlignNumericText(digits, self == 0, self > 0));
        }