2 // System.NumberFormatter.cs
5 // Kazuki Oikawa (kazuki@panicode.com)
8 using System.Collections;
9 using System.Globalization;
16 static char[] digitLowerTable = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
17 static char[] digitUpperTable = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
19 #region NumberToString
20 public static string NumberToString (string format, sbyte value, NumberFormatInfo nfi)
25 ParseBasicFormat (format, out specifier, out precision, out custom);
26 if (!custom && (specifier == 'x' || specifier == 'X'))
27 return FormatHexadecimal (value >= 0 ? (ulong)value : (ulong)-value, value >= 0, 1, precision, specifier == 'X');
28 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
30 public static string NumberToString (string format, byte value, NumberFormatInfo nfi)
35 ParseBasicFormat (format, out specifier, out precision, out custom);
36 if (!custom && (specifier == 'x' || specifier == 'X'))
37 return FormatHexadecimal (value, true, 1, precision, specifier == 'X');
38 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
40 public static string NumberToString (string format, ushort value, NumberFormatInfo nfi)
45 ParseBasicFormat (format, out specifier, out precision, out custom);
46 if (!custom && (specifier == 'x' || specifier == 'X'))
47 return FormatHexadecimal (value, true, 2, precision, specifier == 'X');
48 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
50 public static string NumberToString (string format, short value, NumberFormatInfo nfi)
55 ParseBasicFormat (format, out specifier, out precision, out custom);
56 if (!custom && (specifier == 'x' || specifier == 'X'))
57 return FormatHexadecimal (value >= 0 ? (ulong)value : (ulong)-value, value >= 0, 2, precision, specifier == 'X');
58 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
60 public static string NumberToString (string format, uint value, NumberFormatInfo nfi)
65 ParseBasicFormat (format, out specifier, out precision, out custom);
66 if (!custom && (specifier == 'x' || specifier == 'X'))
67 return FormatHexadecimal (value, true, 4, precision, specifier == 'X');
68 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
70 public static string NumberToString (string format, int value, NumberFormatInfo nfi)
75 ParseBasicFormat (format, out specifier, out precision, out custom);
76 if (!custom && (specifier == 'x' || specifier == 'X'))
77 return FormatHexadecimal (value >= 0 ? (ulong)value : (ulong)-(long)value, value >= 0, 4, precision, specifier == 'X');
78 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
80 public static string NumberToString (string format, ulong value, NumberFormatInfo nfi)
85 ParseBasicFormat (format, out specifier, out precision, out custom);
86 if (!custom && (specifier == 'x' || specifier == 'X'))
87 return FormatHexadecimal (value, true, 8, precision, specifier == 'X');
88 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
90 public static string NumberToString (string format, long value, NumberFormatInfo nfi)
95 ParseBasicFormat (format, out specifier, out precision, out custom);
96 if (!custom && (specifier == 'x' || specifier == 'X'))
97 return FormatHexadecimal (value >= 0 ? (ulong)value : (ulong)-value, value >= 0, 8, precision, specifier == 'X');
98 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
100 public static string NumberToString (string format, float value, NumberFormatInfo nfi)
105 ParseBasicFormat (format, out specifier, out precision, out custom);
106 if (!custom && (specifier == 'x' || specifier == 'X')) throw new FormatException ();
107 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
109 public static string NumberToString (string format, double value, NumberFormatInfo nfi)
114 ParseBasicFormat (format, out specifier, out precision, out custom);
115 if (!custom && (specifier == 'x' || specifier == 'X')) throw new FormatException ();
116 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
118 public static string NumberToString (string format, decimal value, NumberFormatInfo nfi)
123 ParseBasicFormat (format, out specifier, out precision, out custom);
124 if (!custom && (specifier == 'x' || specifier == 'X')) throw new FormatException ();
125 return NumberToString (format, new NumberStore (value), nfi, specifier, precision, custom);
127 public static string NumberToString (string format, NumberStore ns, NumberFormatInfo nfi, char specifier, int precision, bool custom)
130 return nfi.NaNSymbol;
134 return nfi.PositiveInfinitySymbol;
136 return nfi.NegativeInfinitySymbol;
140 nfi = NumberFormatInfo.GetInstance (null);
143 if (ns.IsFloatingSource)
144 ns.RoundEffectiveDigits (ns.DefaultPrecision);
145 return FormatCustom (format, ns, nfi);
148 if (ns.IsFloatingSource) {
158 ns.RoundEffectiveDigits (ns.DefaultPrecision);
163 ns.RoundEffectiveDigits (ns.DefaultPrecision, ns.IsBankerApplicable, true);
165 ns.RoundEffectiveDigits (precision);
169 ns.RoundEffectiveDigits (ns.DefaultMaxPrecision);
171 // FIXME: it is a quick workaround for non-roundtrip issue (bug #320433).
172 string orgStr = FormatGeneral (ns, ns.DefaultPrecision, nfi, true, true);
173 double orgValue = double.Parse (orgStr);
174 NumberStore tmpNS = new NumberStore (orgValue);
175 tmpNS.RoundEffectiveDigits (tmpNS.DefaultMaxPrecision);
176 tmpNS.RoundEffectiveDigits (tmpNS.DefaultMaxPrecision - 1);
177 string tmpStr = FormatGeneral (tmpNS, ns.DefaultPrecision, nfi, true, true);
178 double tmpValue = double.Parse (tmpStr);
179 if (orgValue == tmpValue && orgStr.Length - tmpStr.Length > 1)
184 if (precision > ns.DefaultPrecision)
185 ns.RoundEffectiveDigits (precision + 1);
187 ns.RoundEffectiveDigits (ns.DefaultPrecision + 1);
195 return FormatCurrency (ns, precision, nfi);
198 return FormatDecimal (ns, precision, nfi);
201 return FormatExponential (ns, precision, nfi, specifier == 'E');
204 return FormatFixedPoint (ns, precision, nfi);
207 if (ns.IsFloatingSource || ns.IsDecimalSource || precision != -1)
208 return FormatGeneral (ns, precision, nfi, specifier == 'G', false);
209 return FormatDecimal (ns, precision, nfi);
212 return FormatNumber (ns, precision, nfi);
215 return FormatPercent (ns, precision, nfi);
218 if (ns.IsFloatingSource) {
219 return FormatGeneral (ns, ns.DefaultPrecision, nfi, true, true);
221 throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
224 throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
230 private static void ParseBasicFormat (string format, out char specifier, out int precision, out bool custom)
232 if (format == null || format.Length == 0) {
240 specifier = format[0];
243 if (Char.IsLetter (specifier)) {
244 if (format.Length == 1)
249 for (int i = 1; i < format.Length; i++) {
251 if (char.IsDigit (c)) {
252 precision = precision * 10 + (c - '0');
253 if (precision > 99) {
274 private static void ZeroTrimEnd (StringBuilder sb)
276 ZeroTrimEnd (sb, false);
278 private static void ZeroTrimEnd (StringBuilder sb, bool canEmpty)
281 for (int i = sb.Length - 1; (canEmpty ? i >= 0 : i > 0); i --) {
288 sb.Remove (sb.Length - len, len);
293 internal static string FormatCurrency (NumberStore ns, int precision, NumberFormatInfo nfi)
295 precision = (precision >= 0 ? precision : nfi.CurrencyDecimalDigits);
296 ns.RoundDecimal (precision);
297 StringBuilder sb = new StringBuilder (ns.IntegerDigits * 2 + precision * 2 + 16);
298 bool needNegativeSign = !ns.Positive && !ns.ZeroOnly;
300 if (!needNegativeSign) {
301 switch (nfi.CurrencyPositivePattern) {
303 sb.Append (nfi.CurrencySymbol);
306 sb.Append (nfi.CurrencySymbol);
311 switch (nfi.CurrencyNegativePattern) {
314 sb.Append (nfi.CurrencySymbol);
317 sb.Append (nfi.NegativeSign);
318 sb.Append (nfi.CurrencySymbol);
321 sb.Append (nfi.CurrencySymbol);
322 sb.Append (nfi.NegativeSign);
325 sb.Append (nfi.CurrencySymbol);
331 sb.Append (nfi.NegativeSign);
334 sb.Append (nfi.NegativeSign);
337 sb.Append (nfi.NegativeSign);
338 sb.Append (nfi.CurrencySymbol);
342 sb.Append (nfi.CurrencySymbol);
346 sb.Append (nfi.CurrencySymbol);
348 sb.Append (nfi.NegativeSign);
352 sb.Append (nfi.CurrencySymbol);
361 ns.AppendIntegerStringWithGroupSeparator (sb, nfi.CurrencyGroupSizes, nfi.CurrencyGroupSeparator);
365 sb.Append (nfi.CurrencyDecimalSeparator);
366 ns.AppendDecimalString (precision, sb);
369 if (!needNegativeSign) {
370 switch (nfi.CurrencyPositivePattern) {
372 sb.Append (nfi.CurrencySymbol);
376 sb.Append (nfi.CurrencySymbol);
380 switch (nfi.CurrencyNegativePattern) {
385 sb.Append (nfi.NegativeSign);
388 sb.Append (nfi.CurrencySymbol);
392 sb.Append (nfi.CurrencySymbol);
395 sb.Append (nfi.NegativeSign);
396 sb.Append (nfi.CurrencySymbol);
399 sb.Append (nfi.CurrencySymbol);
400 sb.Append (nfi.NegativeSign);
404 sb.Append (nfi.CurrencySymbol);
408 sb.Append (nfi.CurrencySymbol);
409 sb.Append (nfi.NegativeSign);
412 sb.Append (nfi.NegativeSign);
415 sb.Append (nfi.NegativeSign);
417 sb.Append (nfi.CurrencySymbol);
424 sb.Append (nfi.CurrencySymbol);
430 return sb.ToString ();
432 internal static string FormatDecimal (NumberStore ns, int precision, NumberFormatInfo nfi)
434 if (ns.IsFloatingSource || ns.IsDecimalSource)
435 throw new FormatException ();
437 precision = precision > 0 ? precision : 1;
438 precision = ns.IntegerDigits > precision ? ns.IntegerDigits : precision;
440 StringBuilder sb = new StringBuilder (precision + nfi.NegativeSign.Length);
442 if (!ns.Positive && !ns.CheckZeroOnlyInteger ()) {
443 sb.Append (nfi.NegativeSign);
446 ns.AppendIntegerString (precision, sb);
448 return sb.ToString ();
450 internal static string FormatFixedPoint (NumberStore ns, int precision, NumberFormatInfo nfi)
452 precision = precision >= 0 ? precision : nfi.NumberDecimalDigits;
453 ns.RoundDecimal (precision);
455 StringBuilder cb = new StringBuilder (ns.IntegerDigits + precision + nfi.NumberDecimalSeparator.Length);
457 if (!ns.Positive && !ns.ZeroOnly)
458 cb.Append (nfi.NegativeSign);
460 ns.AppendIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb);
463 cb.Append (nfi.NumberDecimalSeparator);
464 ns.AppendDecimalString (precision, cb);
467 return cb.ToString ();
470 internal static string FormatGeneral (NumberStore ns)
472 return FormatGeneral (ns, -1, NumberFormatInfo.CurrentInfo, true, false);
474 internal static string FormatGeneral (NumberStore ns, IFormatProvider provider)
476 return FormatGeneral (ns, -1, NumberFormatInfo.GetInstance (provider), true, false);
478 private static string FormatGeneral (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper, bool roundtrip)
483 precision = precision > 0 ? precision : ns.DefaultPrecision;
486 bool expMode = (ns.IsDecimalSource && precision == ns.DefaultPrecision ? false : (ns.IntegerDigits > precision || ns.DecimalPointPosition <= -4));
488 while (!(ns.DecimalPointPosition == 1 && ns.GetChar (0) != '0')) {
489 if (ns.DecimalPointPosition > 1) {
499 precision = precision < ns.DefaultPrecision + 2 ? (precision < ns.DefaultMaxPrecision ? precision : ns.DefaultMaxPrecision) : ns.DefaultPrecision + 2;
500 StringBuilder cb = new StringBuilder (ns.IntegerDigits + precision + 16);
502 if (ns.RoundDecimal (precision - 1)) {
506 } else if (!roundtrip) {
507 if (ns.IsDecimalSource)
508 ns.RoundPos (precision);
510 ns.RoundDecimal (precision, true, false);
514 cb.Append (nfi.NegativeSign);
517 ns.AppendIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb);
519 if (ns.DecimalDigits > 0) {
520 cb.Append (nfi.NumberDecimalSeparator);
521 ns.AppendDecimalString (ns.DecimalDigits, cb);
531 cb.Append (nfi.PositiveSign);
533 cb.Append (nfi.NegativeSign);
534 exponent = -exponent;
539 } else if (exponent < 10) {
541 cb.Append (digitLowerTable [exponent]);
542 } else if (exponent < 100) {
543 cb.Append (digitLowerTable [exponent / 10 % 10]);
544 cb.Append (digitLowerTable [exponent % 10]);
545 } else if (exponent < 1000) {
546 cb.Append (digitLowerTable [exponent / 100 % 10]);
547 cb.Append (digitLowerTable [exponent / 10 % 10]);
548 cb.Append (digitLowerTable [exponent % 10]);
552 return cb.ToString ();
554 internal static string FormatNumber (NumberStore ns, int precision, NumberFormatInfo nfi)
556 precision = (precision >= 0 ? precision : nfi.NumberDecimalDigits);
557 StringBuilder sb = new StringBuilder(ns.IntegerDigits * 3 + precision);
559 ns.RoundDecimal (precision);
560 bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly);
562 if (needNegativeSign) {
563 switch (nfi.NumberNegativePattern) {
568 sb.Append (nfi.NegativeSign);
571 sb.Append (nfi.NegativeSign);
577 ns.AppendIntegerStringWithGroupSeparator (sb, nfi.NumberGroupSizes, nfi.NumberGroupSeparator);
580 sb.Append (nfi.NumberDecimalSeparator);
581 ns.AppendDecimalString (precision, sb);
584 if (needNegativeSign) {
585 switch (nfi.NumberNegativePattern) {
590 sb.Append (nfi.NegativeSign);
594 sb.Append (nfi.NegativeSign);
599 return sb.ToString ();
601 internal static string FormatPercent (NumberStore ns, int precision, NumberFormatInfo nfi)
603 precision = (precision >= 0 ? precision : nfi.PercentDecimalDigits);
605 ns.RoundDecimal (precision);
606 bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly);
608 StringBuilder sb = new StringBuilder(ns.IntegerDigits * 2 + precision + 16);
610 if (!needNegativeSign) {
611 if (nfi.PercentPositivePattern == 2) {
612 sb.Append (nfi.PercentSymbol);
615 switch (nfi.PercentNegativePattern) {
617 sb.Append (nfi.NegativeSign);
620 sb.Append (nfi.NegativeSign);
623 sb.Append (nfi.NegativeSign);
624 sb.Append (nfi.PercentSymbol);
629 ns.AppendIntegerStringWithGroupSeparator (sb, nfi.PercentGroupSizes, nfi.PercentGroupSeparator);
632 sb.Append (nfi.PercentDecimalSeparator);
633 ns.AppendDecimalString (precision, sb);
636 if (!needNegativeSign) {
637 switch (nfi.PercentPositivePattern) {
640 sb.Append (nfi.PercentSymbol);
643 sb.Append (nfi.PercentSymbol);
647 switch (nfi.PercentNegativePattern) {
650 sb.Append (nfi.PercentSymbol);
653 sb.Append (nfi.PercentSymbol);
658 return sb.ToString ();
660 unsafe static string FormatHexadecimal (ulong value, bool positive, int byteSize, int precision, bool upper)
663 /* for large values the cast to ulong is going to return 0 anyway (at least on x86, possibly a MS/Mono runtime bug) */
666 value = (ulong)(Math.Pow (2, byteSize * 8)) - value;
673 value = (ulong)(256UL - value);
676 value = (ulong)(65536UL - value);
679 value = (ulong)(4294967296UL - value);
688 char[] digits = (upper ? digitUpperTable : digitLowerTable);
689 int size = precision > 16 ? precision : 16;
690 char* buffer = stackalloc char [size];
691 char* last = buffer + size;
695 *--ptr = digits[value & 0xF];
699 while (ptr == last || last - ptr < precision)
702 return new string (ptr, 0, (int)(last - ptr));
704 internal static string FormatExponential (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
710 StringBuilder sb = new StringBuilder (precision + nfi.PositiveSign.Length + 6);
714 sb.Append ('0', precision);
722 sb.Append (nfi.PositiveSign);
725 return sb.ToString ();
729 while (!(ns.DecimalPointPosition == 1 && ns.GetChar (0) != '0')) {
730 if (ns.DecimalPointPosition > 1) {
739 if (ns.RoundDecimal (precision)) {
744 StringBuilder cb = new StringBuilder (ns.DecimalDigits + 1 + 8);
747 cb.Append (nfi.NegativeSign);
750 ns.AppendIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb);
753 cb.Append (nfi.NumberDecimalSeparator);
754 ns.AppendDecimalString (precision, cb);
763 cb.Append (nfi.PositiveSign);
765 cb.Append (nfi.NegativeSign);
766 exponent = -exponent;
771 } else if (exponent < 10) {
773 cb.Append (digitLowerTable [exponent]);
774 } else if (exponent < 100) {
776 cb.Append (digitLowerTable [exponent / 10 % 10]);
777 cb.Append (digitLowerTable [exponent % 10]);
778 } else if (exponent < 1000) {
779 cb.Append (digitLowerTable [exponent / 100 % 10]);
780 cb.Append (digitLowerTable [exponent / 10 % 10]);
781 cb.Append (digitLowerTable [exponent % 10]);
782 /*} else { // exponent range is 0...+-324
785 while (exponent > 0 || --count > 0) {
786 cb.Insert (pos, digitLowerTable [exponent % 10]);
791 return cb.ToString ();
796 internal static string FormatCustom (string format, NumberStore ns, NumberFormatInfo nfi)
798 bool p = ns.Positive;
801 CustomInfo.GetActiveSection (format,ref p, ns.ZeroOnly, ref offset, ref length);
803 return ns.Positive ? String.Empty : nfi.NegativeSign;
807 CustomInfo info = CustomInfo.Parse (format, offset, length, nfi);
809 Console.WriteLine("Format : {0}",format);
810 Console.WriteLine("DecimalDigits : {0}",info.DecimalDigits);
811 Console.WriteLine("DecimalPointPos : {0}",info.DecimalPointPos);
812 Console.WriteLine("DecimalTailSharpDigits : {0}",info.DecimalTailSharpDigits);
813 Console.WriteLine("IntegerDigits : {0}",info.IntegerDigits);
814 Console.WriteLine("IntegerHeadSharpDigits : {0}",info.IntegerHeadSharpDigits);
815 Console.WriteLine("IntegerHeadPos : {0}",info.IntegerHeadPos);
816 Console.WriteLine("UseExponent : {0}",info.UseExponent);
817 Console.WriteLine("ExponentDigits : {0}",info.ExponentDigits);
818 Console.WriteLine("ExponentTailSharpDigits : {0}",info.ExponentTailSharpDigits);
819 Console.WriteLine("ExponentNegativeSignOnly : {0}",info.ExponentNegativeSignOnly);
820 Console.WriteLine("DividePlaces : {0}",info.DividePlaces);
821 Console.WriteLine("Percents : {0}",info.Percents);
822 Console.WriteLine("Permilles : {0}",info.Permilles);
824 StringBuilder sb_int = new StringBuilder(info.IntegerDigits * 2);
825 StringBuilder sb_dec = new StringBuilder(info.DecimalDigits * 2);
826 StringBuilder sb_exp = (info.UseExponent ? new StringBuilder(info.ExponentDigits * 2) : null);
829 if (info.Percents > 0) {
830 ns.Multiply10 (2 * info.Percents);
832 if (info.Permilles > 0) {
833 ns.Multiply10 (3 * info.Permilles);
835 if (info.DividePlaces > 0) {
836 ns.Divide10 (info.DividePlaces);
839 bool expPositive = true;
840 if (info.UseExponent && (info.DecimalDigits > 0 || info.IntegerDigits > 0)) {
843 while (ns.IntegerDigits > info.IntegerDigits) {
846 if (ns.IntegerDigits == 1 && ns.GetChar (0) == '0')
849 while (ns.IntegerDigits < info.IntegerDigits || (ns.IntegerDigits == info.IntegerDigits && ns.GetChar (0) == '0')) {
854 if (!ns.RoundDecimal (info.DecimalDigits))
859 expPositive = diff <= 0;
860 NumberStore.AppendIntegerStringFromUInt32 (sb_exp, (uint)(diff >= 0 ? diff : -diff));
862 ns.RoundDecimal (info.DecimalDigits);
867 if (info.IntegerDigits != 0 || !ns.CheckZeroOnlyInteger ()) {
868 ns.AppendIntegerString (ns.IntegerDigits, sb_int);
870 /* if (sb_int.Length > info.IntegerDigits) {
872 while (sb_int.Length > info.IntegerDigits && len < sb_int.Length) {
873 if (sb_int [len] == '0')
878 sb_int.Remove (0, len);
881 ns.AppendDecimalString (ns.DecimalDigits, sb_dec);
883 if (info.UseExponent) {
884 if (info.DecimalDigits <= 0 && info.IntegerDigits <= 0)
887 if (sb_int.Length < info.IntegerDigits)
888 sb_int.Insert (0, "0", info.IntegerDigits - sb_int.Length);
890 while (sb_exp.Length < info.ExponentDigits - info.ExponentTailSharpDigits)
891 sb_exp.Insert (0, '0');
893 if (expPositive && !info.ExponentNegativeSignOnly)
894 sb_exp.Insert (0, nfi.PositiveSign);
895 else if(!expPositive)
896 sb_exp.Insert (0, nfi.NegativeSign);
898 if (sb_int.Length < info.IntegerDigits - info.IntegerHeadSharpDigits)
899 sb_int.Insert (0, "0", info.IntegerDigits - info.IntegerHeadSharpDigits - sb_int.Length);
900 if (info.IntegerDigits == info.IntegerHeadSharpDigits && NumberStore.IsZeroOnly (sb_int))
901 sb_int.Remove (0, sb_int.Length);
904 ZeroTrimEnd (sb_dec, true);
905 while (sb_dec.Length < info.DecimalDigits - info.DecimalTailSharpDigits)
907 if (sb_dec.Length > info.DecimalDigits)
908 sb_dec.Remove (info.DecimalDigits, sb_dec.Length - info.DecimalDigits);
910 return info.Format (format, offset, length, nfi, ns.Positive, sb_int, sb_dec, sb_exp);
913 private class CustomInfo
915 public bool UseGroup = false;
916 public int DecimalDigits = 0;
917 public int DecimalPointPos = -1;
918 public int DecimalTailSharpDigits = 0;
919 public int IntegerDigits = 0;
920 public int IntegerHeadSharpDigits = 0;
921 public int IntegerHeadPos = 0;
922 public bool UseExponent = false;
923 public int ExponentDigits = 0;
924 public int ExponentTailSharpDigits = 0;
925 public bool ExponentNegativeSignOnly = true;
926 public int DividePlaces = 0;
927 public int Percents = 0;
928 public int Permilles = 0;
930 public static void GetActiveSection (string format, ref bool positive, bool zero, ref int offset, ref int length)
932 int[] lens = new int [3];
936 for (int i = 0; i < format.Length; i++) {
939 if (c == literal || (literal == '\0' && (c == '\"' || c == '\''))) {
947 if (literal == '\0' && format [i] == ';' && (i == 0 || format [i - 1] != '\\')) {
948 lens [index ++] = i - lastPos;
957 length = format.Length;
961 if (positive || zero) {
966 if (lens [0] + 1 < format.Length) {
968 offset = lens [0] + 1;
969 length = format.Length - offset;
979 offset = lens [0] + lens [1] + 2;
980 length = format.Length - offset;
990 offset = lens [0] + 1;
1001 offset = lens [0] + lens [1] + 2;
1012 offset = lens [0] + 1;
1022 throw new ArgumentException ();
1025 public static CustomInfo Parse (string format, int offset, int length, NumberFormatInfo nfi)
1027 char literal = '\0';
1028 bool integerArea = true;
1029 bool decimalArea = false;
1030 bool exponentArea = false;
1031 bool sharpContinues = true;
1033 CustomInfo info = new CustomInfo ();
1034 int groupSeparatorCounter = 0;
1036 for (int i = offset; i - offset < length; i++) {
1037 char c = format [i];
1039 if (c == literal && c != '\0') {
1043 if (literal != '\0')
1046 if (exponentArea && (c != '\0' && c != '0' && c != '#')) {
1047 exponentArea = false;
1048 integerArea = (info.DecimalPointPos < 0);
1049 decimalArea = !integerArea;
1060 if (c == '\"' || c == '\'') {
1065 if (sharpContinues && integerArea)
1066 info.IntegerHeadSharpDigits ++;
1067 else if (decimalArea)
1068 info.DecimalTailSharpDigits ++;
1069 else if (exponentArea)
1070 info.ExponentTailSharpDigits ++;
1075 sharpContinues = false;
1077 info.DecimalTailSharpDigits = 0;
1078 else if (exponentArea)
1079 info.ExponentTailSharpDigits = 0;
1081 if (info.IntegerHeadPos == -1)
1082 info.IntegerHeadPos = i;
1085 info.IntegerDigits ++;
1086 if (groupSeparatorCounter > 0)
1087 info.UseGroup = true;
1088 groupSeparatorCounter = 0;
1089 } else if (decimalArea) {
1090 info.DecimalDigits ++;
1091 } else if (exponentArea) {
1092 info.ExponentDigits ++;
1097 if (info.UseExponent)
1100 info.UseExponent = true;
1101 integerArea = false;
1102 decimalArea = false;
1103 exponentArea = true;
1104 if (i + 1 - offset < length) {
1105 char nc = format [i + 1];
1107 info.ExponentNegativeSignOnly = false;
1108 if (nc == '+' || nc == '-') {
1110 } else if (nc != '0' && nc != '#') {
1111 info.UseExponent = false;
1112 if (info.DecimalPointPos < 0)
1120 integerArea = false;
1122 exponentArea = false;
1123 if (info.DecimalPointPos == -1)
1124 info.DecimalPointPos = i;
1133 if (integerArea && info.IntegerDigits > 0)
1134 groupSeparatorCounter ++;
1141 if (info.ExponentDigits == 0)
1142 info.UseExponent = false;
1144 info.IntegerHeadSharpDigits = 0;
1146 if (info.DecimalDigits == 0)
1147 info.DecimalPointPos = -1;
1149 info.DividePlaces += groupSeparatorCounter * 3;
1154 public string Format (string format, int offset, int length, NumberFormatInfo nfi, bool positive, StringBuilder sb_int, StringBuilder sb_dec, StringBuilder sb_exp)
1156 StringBuilder sb = new StringBuilder ();
1157 char literal = '\0';
1158 bool integerArea = true;
1159 bool decimalArea = false;
1160 int intSharpCounter = 0;
1161 int sb_int_index = 0;
1162 int sb_dec_index = 0;
1164 int[] groups = nfi.NumberGroupSizes;
1165 string groupSeparator = nfi.NumberGroupSeparator;
1166 int intLen = 0, total = 0, groupIndex = 0, counter = 0, groupSize = 0, fraction = 0;
1167 if (UseGroup && groups.Length > 0) {
1168 intLen = sb_int.Length;
1169 for (int i = 0; i < groups.Length; i++) {
1170 total += groups [i];
1171 if (total <= intLen)
1174 groupSize = groups [groupIndex];
1175 fraction = intLen > total ? intLen - total : 0;
1176 if (groupSize == 0) {
1177 while (groupIndex >= 0 && groups [groupIndex] == 0)
1180 groupSize = fraction > 0 ? fraction : groups [groupIndex];
1182 if (fraction == 0) {
1183 counter = groupSize;
1185 groupIndex += fraction / groupSize;
1186 counter = fraction % groupSize;
1188 counter = groupSize;
1196 for (int i = offset; i - offset < length; i++) {
1197 char c = format [i];
1199 if (c == literal && c != '\0') {
1203 if (literal != '\0') {
1211 if (i - offset < length)
1212 sb.Append (format [i]);
1216 if (c == '\"' || c == '\'') {
1225 if (IntegerDigits - intSharpCounter < sb_int.Length + sb_int_index || c == '0')
1226 while (IntegerDigits - intSharpCounter + sb_int_index < sb_int.Length) {
1227 sb.Append (sb_int[ sb_int_index++]);
1228 if (UseGroup && --intLen > 0 && --counter == 0) {
1229 sb.Append (groupSeparator);
1230 if (--groupIndex < groups.Length && groupIndex >= 0)
1231 groupSize = groups [groupIndex];
1232 counter = groupSize;
1236 } else if (decimalArea) {
1237 if (sb_dec_index < sb_dec.Length)
1238 sb.Append (sb_dec [sb_dec_index++]);
1246 if (sb_exp == null || !UseExponent) {
1255 for (q = i + 1; q - offset < length; q++) {
1256 if (format [q] == '0') {
1260 if (q == i + 1 && (format [q] == '+' || format [q] == '-')) {
1270 integerArea = (DecimalPointPos < 0);
1271 decimalArea = !integerArea;
1281 if (DecimalPointPos == i) {
1282 if (DecimalDigits > 0) {
1283 while (sb_int_index < sb_int.Length)
1284 sb.Append (sb_int [sb_int_index++]);
1286 if (sb_dec.Length > 0)
1287 sb.Append (nfi.NumberDecimalSeparator);
1289 integerArea = false;
1295 sb.Append (nfi.PercentSymbol);
1298 sb.Append (nfi.PerMilleSymbol);
1307 sb.Insert (0, nfi.NegativeSign);
1309 return sb.ToString ();
1315 #region Internal structures
1316 internal struct NumberStore
1323 int _defMaxPrecision;
1328 static uint [] IntList = new uint [] {
1341 static ulong [] ULongList = new ulong [] {
1360 1000000000000000000,
1361 10000000000000000000,
1364 #region Constructors
1365 public NumberStore (long value)
1367 _infinity = _NaN = false;
1369 _defMaxPrecision = _defPrecision = 19;
1370 _positive = value >= 0;
1373 _digits = new byte []{0};
1378 ulong v = (ulong)(_positive ? value : -value);
1390 else if (v < 100000)
1392 else if (v < 1000000)
1394 else if (v < 10000000)
1396 else if (v < 100000000)
1398 else if (v < 1000000000)
1400 else if (v < 10000000000)
1402 else if (v < 100000000000)
1404 else if (v < 1000000000000)
1406 else if (v < 10000000000000)
1408 else if (v < 100000000000000)
1410 else if (v < 1000000000000000)
1412 else if (v < 10000000000000000)
1414 else if (v < 100000000000000000)
1416 else if (v < 1000000000000000000)
1421 _digits = new byte [i + 1];
1423 ulong n = v / ULongList [i];
1424 _digits [j++] = (byte)n;
1425 v -= ULongList [i--] * n;
1428 _decPointPos = _digits.Length;
1430 public NumberStore (int value)
1432 _infinity = _NaN = false;
1434 _defMaxPrecision = _defPrecision = 10;
1435 _positive = value >= 0;
1438 _digits = new byte []{0};
1443 uint v = (uint)(_positive ? value : -value);
1455 else if (v < 100000)
1457 else if (v < 1000000)
1459 else if (v < 10000000)
1461 else if (v < 100000000)
1463 else if (v < 1000000000)
1468 _digits = new byte [i + 1];
1470 uint n = v / IntList [i];
1471 _digits [j++] = (byte)n;
1472 v -= IntList [i--] * n;
1475 _decPointPos = _digits.Length;
1477 public NumberStore (short value) : this ((int)value)
1480 _defMaxPrecision = _defPrecision = 5;
1482 public NumberStore (sbyte value) : this ((int)value)
1485 _defMaxPrecision = _defPrecision = 3;
1488 public NumberStore (ulong value)
1490 _infinity = _NaN = false;
1492 _defMaxPrecision = _defPrecision = 20;
1496 _digits = new byte []{0};
1505 else if (value < 100)
1507 else if (value < 1000)
1509 else if (value < 10000)
1511 else if (value < 100000)
1513 else if (value < 1000000)
1515 else if (value < 10000000)
1517 else if (value < 100000000)
1519 else if (value < 1000000000)
1521 else if (value < 10000000000)
1523 else if (value < 100000000000)
1525 else if (value < 1000000000000)
1527 else if (value < 10000000000000)
1529 else if (value < 100000000000000)
1531 else if (value < 1000000000000000)
1533 else if (value < 10000000000000000)
1535 else if (value < 100000000000000000)
1537 else if (value < 1000000000000000000)
1539 else if (value < 10000000000000000000)
1544 _digits = new byte [i + 1];
1546 ulong n = value / ULongList [i];
1547 _digits [j++] = (byte)n;
1548 value -= ULongList [i--] * n;
1551 _decPointPos = _digits.Length;
1553 public NumberStore (uint value)
1555 _infinity = _NaN = false;
1558 _defMaxPrecision = _defPrecision = 10;
1561 _digits = new byte []{0};
1570 else if (value < 100)
1572 else if (value < 1000)
1574 else if (value < 10000)
1576 else if (value < 100000)
1578 else if (value < 1000000)
1580 else if (value < 10000000)
1582 else if (value < 100000000)
1584 else if (value < 1000000000)
1589 _digits = new byte [i + 1];
1591 uint n = value / IntList [i];
1592 _digits [j++] = (byte)n;
1593 value -= IntList [i--] * n;
1596 _decPointPos = _digits.Length;
1598 public NumberStore (ushort value) : this ((uint)value)
1601 _defMaxPrecision = _defPrecision = 5;
1603 public NumberStore (byte value) : this ((uint)value)
1606 _defMaxPrecision = _defPrecision = 3;
1609 public NumberStore(double value)
1614 _defMaxPrecision = _defPrecision + 2;
1616 if (double.IsNaN (value) || double.IsInfinity (value)) {
1617 _NaN = double.IsNaN (value);
1618 _infinity = double.IsInfinity (value);
1619 _positive = value > 0;
1623 _NaN = _infinity = false;
1626 long bits = BitConverter.DoubleToInt64Bits (value);
1627 _positive = (bits >= 0);
1628 int e = (int) ((bits >> 52) & 0x7ffL);
1629 long m = bits & 0xfffffffffffffL;
1631 if (e == 0 && m == 0) {
1633 _digits = new byte []{0};
1640 } else if (e != 0) {
1647 while ((m & 1) == 0) {
1655 byte[] temp = new byte [56];
1656 for (int i = temp.Length - 1; i >= 0; i--, length++) {
1657 temp [i] = (byte)(mt % 10);
1663 _decPointPos = temp.Length - 1;
1666 for (int i = 0; i < e; i++) {
1667 if (MultiplyBy (ref temp, ref length, 2)) {
1672 for (int i = 0; i < -e; i++) {
1673 if (MultiplyBy (ref temp, ref length, 5)) {
1682 for (int i = 0; i < temp.Length; i++)
1683 if (temp [i] != 0) {
1684 _decPointPos -= i - 1;
1685 _digits = new byte [temp.Length - i];
1686 for (int q = i; q < temp.Length; q++) {
1687 _digits [q - i] = temp [q];
1689 ulv = ulv * 10 + temp [q];
1696 RoundEffectiveDigits (17, true, true);
1698 public NumberStore(float value)
1703 _defMaxPrecision = _defPrecision + 2;
1705 if (float.IsNaN (value) || float.IsInfinity (value)) {
1706 _NaN = float.IsNaN (value);
1707 _infinity = float.IsInfinity (value);
1708 _positive = value > 0;
1712 _infinity = _NaN = false;
1714 long bits = BitConverter.DoubleToInt64Bits (value);
1715 _positive = (bits >= 0);
1716 int e = (int) ((bits >> 52) & 0x7ffL);
1717 long m = bits & 0xfffffffffffffL;
1719 if (e == 0 && m == 0) {
1721 _digits = new byte []{0};
1728 } else if (e != 0) {
1735 while ((m & 1) == 0) {
1743 byte[] temp = new byte [26];
1744 for (int i = temp.Length - 1; i >= 0; i--, length++) {
1745 temp [i] = (byte)(mt % 10);
1751 _decPointPos = temp.Length - 1;
1754 for (int i = 0; i < e; i++) {
1755 if (MultiplyBy (ref temp, ref length, 2)) {
1760 for (int i = 0; i < -e; i++) {
1761 if (MultiplyBy (ref temp, ref length, 5)) {
1770 for (int i = 0; i < temp.Length; i++)
1771 if (temp [i] != 0) {
1772 _decPointPos -= i - 1;
1773 _digits = new byte [temp.Length - i];
1774 for (int q = i; q < temp.Length; q++) {
1775 _digits [q - i] = temp [q];
1777 ulv = ulv * 10 + temp [q];
1784 RoundEffectiveDigits (9, true, true);
1787 internal bool MultiplyBy (ref byte[] buffer,ref int length, int amount)
1791 int start = buffer.Length - length - 1;
1792 if (start < 0) start = 0;
1794 for (int i = buffer.Length - 1; i > start; i--) {
1795 ret = buffer [i] * amount + mod;
1797 buffer [i] = (byte)(ret % 10);
1801 length = buffer.Length - start;
1804 buffer [0] = (byte)mod;
1805 Array.Copy (buffer, 0, buffer, 1, buffer.Length - 1);
1810 buffer [start] = (byte)mod;
1818 public NumberStore (decimal value)
1820 int[] bits = decimal.GetBits (value);
1821 _positive = (bits [3] & 0x80000000) == 0;
1822 bits[3] = bits [3] & 0x7FFFFFFF;
1823 int ss = (bits [3] & 0x1F0000) >> 16;
1824 ulong lo = (ulong)((((ulong)bits[1]) << 32) | (uint)bits [0]);
1825 ulong hi = (uint)bits [2];
1829 while (hi > 0 || lo > 0) {
1831 DivideDecimal (ref lo, ref hi, 10, ref rest);
1834 lo = (ulong)((((ulong)bits[1]) << 32) | (uint)bits [0]);
1835 hi = (uint)bits [2];
1837 _digits = new byte [digits];
1839 while (hi > 0 || lo > 0) {
1840 DivideDecimal (ref lo, ref hi, 10, ref rest);
1841 _digits [--i] = (byte)rest;
1844 _infinity = _NaN = false;
1845 _decPointPos = _digits.Length - ss;
1846 _defPrecision = _defMaxPrecision = 100;
1849 static int DivideDecimal (ref ulong lo, ref ulong hi, uint factor, ref uint rest)
1854 a = (uint)(h >> 32);
1862 hi = b << 32 | (uint)c;
1865 a |= (uint)(h >> 32);
1872 lo = b << 32 | (uint)c;
1877 return (a >= factor || (a == factor && (c & 1) == 1)) ? 1 : 0;
1881 #region Public Property
1884 get { return _NaN; }
1886 public bool IsInfinity {
1887 get { return _infinity; }
1889 public int DecimalPointPosition {
1890 get { return _decPointPos; }
1892 public bool Positive {
1893 get { return _positive; }
1894 set { _positive = value;}
1896 public int DefaultPrecision {
1897 get { return _defPrecision; }
1899 public int DefaultMaxPrecision {
1900 get { return _defMaxPrecision; }
1902 public int DefaultByteSize {
1903 get { return _defByteSize; }
1905 public bool HasDecimal {
1906 get { return _digits.Length > _decPointPos; }
1908 public int IntegerDigits {
1909 get { return _decPointPos > 0 ? _decPointPos : 1; }
1911 public int DecimalDigits {
1912 get { return HasDecimal ? _digits.Length - _decPointPos : 0; }
1914 public bool IsFloatingSource {
1915 get { return _defPrecision == 15 || _defPrecision == 7; }
1917 public bool IsDecimalSource {
1918 get { return _defPrecision > 30; }
1920 public bool IsBankerApplicable {
1922 if ((_digits == null) || (_digits.Length < 2))
1924 return ((_digits [_digits.Length - 2] & 1) == 1);
1927 public bool ZeroOnly {
1929 for (int i = 0; i < _digits.Length; i++)
1930 if (_digits [i] != 0)
1937 #region Public Method
1940 public bool RoundPos (int pos)
1942 return RoundPos (pos, true);
1944 public bool RoundPos (int pos, bool carryFive)
1948 if (_decPointPos <= 0)
1949 pos = pos - _decPointPos - 1;
1951 if (pos >= _digits.Length)
1955 _digits = new byte [1];
1962 for (int i = pos; i >= 0; i--) {
1963 RoundHelper (i, carryFive, ref carry);
1969 byte[] temp = new byte [_digits.Length + 1];
1970 _digits.CopyTo (temp, 1);
1977 for (int i = pos; i < _digits.Length; i++)
1979 TrimDecimalEndZeros ();
1983 public bool RoundDecimal (int decimals)
1985 return RoundDecimal (decimals, true, true);
1987 public bool RoundDecimal (int decimals, bool carryFive, bool countZero)
1991 if (countZero || (_decPointPos > 0))
1992 decimals += _decPointPos;
1994 if (!HasDecimal || decimals >= _digits.Length)
1998 _digits = new byte [1];
2005 for (int i = decimals; i >= 0; i--) {
2006 RoundHelper (i, carryFive, ref carry);
2012 byte[] temp = new byte [_digits.Length + 1];
2013 _digits.CopyTo (temp, 1);
2020 for (int i = decimals; i < _digits.Length; i++)
2022 TrimDecimalEndZeros ();
2026 void RoundHelper (int index, bool carryFive, ref bool carry)
2029 if (_digits [index] == 9) {
2031 _digits [index] = 0;
2036 } else if (_digits [index] >= (carryFive ? 5 : 6)) {
2040 public bool RoundEffectiveDigits (int digits)
2042 return RoundEffectiveDigits (digits, true, true);
2044 public bool RoundEffectiveDigits (int digits, bool carryFive, bool carryEven)
2048 if (digits >= _digits.Length || digits < 0)
2051 if (digits + 1 < _digits.Length && _digits [digits + 1] == 5 && _digits [digits] % 2 == (carryEven ? 0 : 1))
2054 /// are we cutting from the maximum precision ?
2055 if (_digits.Length == _defMaxPrecision) {
2056 // special case if we *aren't* cutting inside the extra precision (e.g. 16 on 17)
2057 if (digits != _defMaxPrecision - 1) {
2058 // ok, here we look at the *two* extra numbers we're keeping
2059 // (we keep 17 digits while the true precision is 15 digits).
2060 int extra = _digits[_defMaxPrecision - 2] * 10 + _digits[_defMaxPrecision - 1];
2061 carry = (extra >= 50);
2063 _digits[_defMaxPrecision - 2] = 0;
2064 _digits[_defMaxPrecision - 1] = 0;
2065 int d = _digits.Length - 3;
2066 CarryPropagation (ref d, carryFive, ref carry);
2070 CarryPropagation (ref digits, carryFive, ref carry);
2072 for (int i = digits; i < _digits.Length; i++)
2074 TrimDecimalEndZeros ();
2079 private void CarryPropagation (ref int digits, bool carryFive, ref bool carry)
2081 for (int i = digits; i >= 0; i--) {
2082 RoundHelper (i, carryFive, ref carry);
2088 byte[] temp = new byte[_digits.Length + 1];
2089 _digits.CopyTo (temp, 1);
2100 public void TrimDecimalEndZeros ()
2103 for (int i = _digits.Length - 1; i >= 0; i --) {
2104 if (_digits [i] != 0)
2110 byte[] temp = new byte [_digits.Length - len];
2111 Array.Copy (_digits, 0, temp, 0, temp.Length);
2115 public void TrimIntegerStartZeros ()
2117 if (_decPointPos < 0 && _decPointPos >= _digits.Length)
2121 for (int i = 0; i < _decPointPos && i < _digits.Length; i++) {
2122 if (_digits [i] != 0)
2127 if (len == _decPointPos)
2130 if (len == _digits.Length) {
2131 _digits = new byte [1];
2135 } else if (len > 0) {
2136 byte[] temp = new byte [_digits.Length - len];
2137 Array.Copy (_digits, len, temp, 0, temp.Length);
2139 _decPointPos -= len;
2146 public void AppendIntegerString (int minLength, StringBuilder cb)
2148 if (IntegerDigits == 0) {
2149 cb.Append ('0', minLength);
2152 if (_decPointPos <= 0) {
2153 cb.Append ('0', minLength);
2157 if (_decPointPos < minLength)
2158 cb.Append ('0', minLength - _decPointPos);
2160 for (int i = 0; i < _decPointPos; i++) {
2161 if (i < _digits.Length)
2162 cb.Append ((char)('0' + _digits [i]));
2167 public void AppendIntegerStringWithGroupSeparator (StringBuilder sb, int[] groups, string groupSeparator)
2169 if (_decPointPos <= 0) {
2174 int intLen = IntegerDigits;
2177 for (int i = 0; i < groups.Length; i++) {
2178 total += groups [i];
2179 if (total <= intLen)
2183 if (groups.Length > 0 && total > 0) {
2185 int groupSize = groups [groupIndex];
2186 int fraction = intLen > total ? intLen - total : 0;
2187 if (groupSize == 0) {
2188 while (groupIndex >= 0 && groups [groupIndex] == 0)
2191 groupSize = fraction > 0 ? fraction : groups [groupIndex];
2193 if (fraction == 0) {
2194 counter = groupSize;
2196 groupIndex += fraction / groupSize;
2197 counter = fraction % groupSize;
2199 counter = groupSize;
2204 for (int i = 0; i < _decPointPos; i++) {
2205 if (i < _digits.Length) {
2206 sb.Append ((char)('0' + _digits [i]));
2211 if (i < intLen - 1 && --counter == 0) {
2212 sb.Append (groupSeparator);
2213 if (--groupIndex < groups.Length && groupIndex >= 0)
2214 groupSize = groups [groupIndex];
2215 counter = groupSize;
2219 for (int i = 0; i < _decPointPos; i++) {
2220 if (i < _digits.Length) {
2221 sb.Append ((char)('0' + _digits [i]));
2231 public string GetDecimalString (int precision)
2234 return new string ('0', precision);
2236 StringBuilder sb = new StringBuilder (precision);
2237 for (int i = _decPointPos; i < _digits.Length && i < precision + _decPointPos; i++) {
2239 sb.Append ((char)('0' + _digits [i]));
2243 if (sb.Length < precision)
2244 sb.Append ('0', precision - sb.Length);
2245 else if (sb.Length > precision)
2246 sb.Remove (0, precision);
2247 return sb.ToString ();
2250 public void AppendDecimalString (int precision, StringBuilder cb)
2253 cb.Append ('0', precision);
2257 int i = _decPointPos;
2258 for (; i < _digits.Length && i < precision + _decPointPos; i++) {
2260 cb.Append ((char)('0' + _digits [i]));
2267 cb.Append ('0', precision - i);
2272 public bool CheckZeroOnlyInteger ()
2274 for (int i = 0; i < _decPointPos && i < _digits.Length; i++) {
2275 if (_digits [i] != 0)
2280 public void Multiply10 (int count)
2285 _decPointPos += count;
2287 TrimIntegerStartZeros ();
2289 public void Divide10 (int count)
2294 _decPointPos -= count;
2296 public override string ToString()
2298 StringBuilder sb = new StringBuilder ();
2299 AppendIntegerString (IntegerDigits, sb);
2302 AppendDecimalString (DecimalDigits, sb);
2304 return sb.ToString ();
2306 public char GetChar (int pos)
2308 if (_decPointPos <= 0)
2309 pos += _decPointPos - 1;
2311 if (pos < 0 || pos >= _digits.Length)
2314 return (char)('0' + _digits [pos]);
2316 public byte GetDigitByte (int pos)
2318 if (_decPointPos <= 0)
2319 pos += _decPointPos - 1;
2321 if (pos < 0 || pos >= _digits.Length)
2324 return _digits [pos];
2326 public NumberStore GetClone ()
2328 NumberStore ns = new NumberStore ();
2330 ns._decPointPos = this._decPointPos;
2331 ns._defMaxPrecision = this._defMaxPrecision;
2332 ns._defPrecision = this._defPrecision;
2333 ns._digits = (byte[])this._digits.Clone ();
2334 ns._infinity = this._infinity;
2335 ns._NaN = this._NaN;
2336 ns._positive = this._positive;
2340 public int GetDecimalPointPos ()
2342 return _decPointPos;
2344 public void SetDecimalPointPos (int dp)
2352 #region Public Static Method
2353 public static bool IsZeroOnly (StringBuilder sb)
2355 for (int i = 0; i < sb.Length; i++)
2356 if (char.IsDigit (sb [i]) && sb [i] != '0')
2360 public static void AppendIntegerStringFromUInt32 (StringBuilder sb, uint v)
2363 throw new ArgumentException ();
2367 if (v >= 1000000000)
2369 else if (v >= 100000000)
2371 else if (v >= 10000000)
2373 else if (v >= 1000000)
2375 else if (v >= 100000)
2377 else if (v >= 10000)
2388 uint n = v / IntList [i];
2389 sb.Append (NumberFormatter.digitLowerTable [n]);
2390 v -= IntList [i--] * n;