1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Globalization;
6 using System.Runtime.CompilerServices;
10 // The Number class implements methods for formatting and parsing
11 // numeric values. To format and parse numeric values, applications should
12 // use the Format and Parse methods provided by the numeric
13 // classes (Byte, Int16, Int32, Int64,
14 // Single, Double, Currency, and Decimal). Those
15 // Format and Parse methods share a common implementation
16 // provided by this class, and are thus documented in detail here.
20 // The Format methods provided by the numeric classes are all of the
23 // public static String Format(XXX value, String format);
24 // public static String Format(XXX value, String format, NumberFormatInfo info);
26 // where XXX is the name of the particular numeric class. The methods convert
27 // the numeric value to a string using the format string given by the
28 // format parameter. If the format parameter is null or
29 // an empty string, the number is formatted as if the string "G" (general
30 // format) was specified. The info parameter specifies the
31 // NumberFormatInfo instance to use when formatting the number. If the
32 // info parameter is null or omitted, the numeric formatting information
33 // is obtained from the current culture. The NumberFormatInfo supplies
34 // such information as the characters to use for decimal and thousand
35 // separators, and the spelling and placement of currency symbols in monetary
38 // Format strings fall into two categories: Standard format strings and
39 // user-defined format strings. A format string consisting of a single
40 // alphabetic character (A-Z or a-z), optionally followed by a sequence of
41 // digits (0-9), is a standard format string. All other format strings are
42 // used-defined format strings.
44 // A standard format string takes the form Axx, where A is an
45 // alphabetic character called the format specifier and xx is a
46 // sequence of digits called the precision specifier. The format
47 // specifier controls the type of formatting applied to the number and the
48 // precision specifier controls the number of significant digits or decimal
49 // places of the formatting operation. The following table describes the
50 // supported standard formats.
52 // C c - Currency format. The number is
53 // converted to a string that represents a currency amount. The conversion is
54 // controlled by the currency format information of the NumberFormatInfo
55 // used to format the number. The precision specifier indicates the desired
56 // number of decimal places. If the precision specifier is omitted, the default
57 // currency precision given by the NumberFormatInfo is used.
59 // D d - Decimal format. This format is
60 // supported for integral types only. The number is converted to a string of
61 // decimal digits, prefixed by a minus sign if the number is negative. The
62 // precision specifier indicates the minimum number of digits desired in the
63 // resulting string. If required, the number will be left-padded with zeros to
64 // produce the number of digits given by the precision specifier.
66 // E e Engineering (scientific) format.
67 // The number is converted to a string of the form
68 // "-d.ddd...E+ddd" or "-d.ddd...e+ddd", where each
69 // 'd' indicates a digit (0-9). The string starts with a minus sign if the
70 // number is negative, and one digit always precedes the decimal point. The
71 // precision specifier indicates the desired number of digits after the decimal
72 // point. If the precision specifier is omitted, a default of 6 digits after
73 // the decimal point is used. The format specifier indicates whether to prefix
74 // the exponent with an 'E' or an 'e'. The exponent is always consists of a
75 // plus or minus sign and three digits.
77 // F f Fixed point format. The number is
78 // converted to a string of the form "-ddd.ddd....", where each
79 // 'd' indicates a digit (0-9). The string starts with a minus sign if the
80 // number is negative. The precision specifier indicates the desired number of
81 // decimal places. If the precision specifier is omitted, the default numeric
82 // precision given by the NumberFormatInfo is used.
84 // G g - General format. The number is
85 // converted to the shortest possible decimal representation using fixed point
86 // or scientific format. The precision specifier determines the number of
87 // significant digits in the resulting string. If the precision specifier is
88 // omitted, the number of significant digits is determined by the type of the
89 // number being converted (10 for int, 19 for long, 7 for
90 // float, 15 for double, 19 for Currency, and 29 for
91 // Decimal). Trailing zeros after the decimal point are removed, and the
92 // resulting string contains a decimal point only if required. The resulting
93 // string uses fixed point format if the exponent of the number is less than
94 // the number of significant digits and greater than or equal to -4. Otherwise,
95 // the resulting string uses scientific format, and the case of the format
96 // specifier controls whether the exponent is prefixed with an 'E' or an
99 // N n Number format. The number is
100 // converted to a string of the form "-d,ddd,ddd.ddd....", where
101 // each 'd' indicates a digit (0-9). The string starts with a minus sign if the
102 // number is negative. Thousand separators are inserted between each group of
103 // three digits to the left of the decimal point. The precision specifier
104 // indicates the desired number of decimal places. If the precision specifier
105 // is omitted, the default numeric precision given by the
106 // NumberFormatInfo is used.
108 // X x - Hexadecimal format. This format is
109 // supported for integral types only. The number is converted to a string of
110 // hexadecimal digits. The format specifier indicates whether to use upper or
111 // lower case characters for the hexadecimal digits above 9 ('X' for 'ABCDEF',
112 // and 'x' for 'abcdef'). The precision specifier indicates the minimum number
113 // of digits desired in the resulting string. If required, the number will be
114 // left-padded with zeros to produce the number of digits given by the
115 // precision specifier.
117 // Some examples of standard format strings and their results are shown in the
118 // table below. (The examples all assume a default NumberFormatInfo.)
120 // Value Format Result
121 // 12345.6789 C $12,345.68
122 // -12345.6789 C ($12,345.68)
125 // 12345.6789 E 1.234568E+004
126 // 12345.6789 E10 1.2345678900E+004
127 // 12345.6789 e4 1.2346e+004
128 // 12345.6789 F 12345.68
129 // 12345.6789 F0 12346
130 // 12345.6789 F6 12345.678900
131 // 12345.6789 G 12345.6789
132 // 12345.6789 G7 12345.68
133 // 123456789 G7 1.234568E8
134 // 12345.6789 N 12,345.68
135 // 123456789 N4 123,456,789.0000
138 // 0x2c45e X8 0002C45E
140 // Format strings that do not start with an alphabetic character, or that start
141 // with an alphabetic character followed by a non-digit, are called
142 // user-defined format strings. The following table describes the formatting
143 // characters that are supported in user defined format strings.
146 // 0 - Digit placeholder. If the value being
147 // formatted has a digit in the position where the '0' appears in the format
148 // string, then that digit is copied to the output string. Otherwise, a '0' is
149 // stored in that position in the output string. The position of the leftmost
150 // '0' before the decimal point and the rightmost '0' after the decimal point
151 // determines the range of digits that are always present in the output
154 // # - Digit placeholder. If the value being
155 // formatted has a digit in the position where the '#' appears in the format
156 // string, then that digit is copied to the output string. Otherwise, nothing
157 // is stored in that position in the output string.
159 // . - Decimal point. The first '.' character
160 // in the format string determines the location of the decimal separator in the
161 // formatted value; any additional '.' characters are ignored. The actual
162 // character used as a the decimal separator in the output string is given by
163 // the NumberFormatInfo used to format the number.
165 // , - Thousand separator and number scaling.
166 // The ',' character serves two purposes. First, if the format string contains
167 // a ',' character between two digit placeholders (0 or #) and to the left of
168 // the decimal point if one is present, then the output will have thousand
169 // separators inserted between each group of three digits to the left of the
170 // decimal separator. The actual character used as a the decimal separator in
171 // the output string is given by the NumberFormatInfo used to format the
172 // number. Second, if the format string contains one or more ',' characters
173 // immediately to the left of the decimal point, or after the last digit
174 // placeholder if there is no decimal point, then the number will be divided by
175 // 1000 times the number of ',' characters before it is formatted. For example,
176 // the format string '0,,' will represent 100 million as just 100. Use of the
177 // ',' character to indicate scaling does not also cause the formatted number
178 // to have thousand separators. Thus, to scale a number by 1 million and insert
179 // thousand separators you would use the format string '#,##0,,'.
181 // % - Percentage placeholder. The presence of
182 // a '%' character in the format string causes the number to be multiplied by
183 // 100 before it is formatted. The '%' character itself is inserted in the
184 // output string where it appears in the format string.
186 // E+ E- e+ e- - Scientific notation.
187 // If any of the strings 'E+', 'E-', 'e+', or 'e-' are present in the format
188 // string and are immediately followed by at least one '0' character, then the
189 // number is formatted using scientific notation with an 'E' or 'e' inserted
190 // between the number and the exponent. The number of '0' characters following
191 // the scientific notation indicator determines the minimum number of digits to
192 // output for the exponent. The 'E+' and 'e+' formats indicate that a sign
193 // character (plus or minus) should always precede the exponent. The 'E-' and
194 // 'e-' formats indicate that a sign character should only precede negative
197 // \ - Literal character. A backslash character
198 // causes the next character in the format string to be copied to the output
199 // string as-is. The backslash itself isn't copied, so to place a backslash
200 // character in the output string, use two backslashes (\\) in the format
203 // 'ABC' "ABC" - Literal string. Characters
204 // enclosed in single or double quotation marks are copied to the output string
205 // as-is and do not affect formatting.
207 // ; - Section separator. The ';' character is
208 // used to separate sections for positive, negative, and zero numbers in the
211 // Other - All other characters are copied to
212 // the output string in the position they appear.
214 // For fixed point formats (formats not containing an 'E+', 'E-', 'e+', or
215 // 'e-'), the number is rounded to as many decimal places as there are digit
216 // placeholders to the right of the decimal point. If the format string does
217 // not contain a decimal point, the number is rounded to the nearest
218 // integer. If the number has more digits than there are digit placeholders to
219 // the left of the decimal point, the extra digits are copied to the output
220 // string immediately before the first digit placeholder.
222 // For scientific formats, the number is rounded to as many significant digits
223 // as there are digit placeholders in the format string.
225 // To allow for different formatting of positive, negative, and zero values, a
226 // user-defined format string may contain up to three sections separated by
227 // semicolons. The results of having one, two, or three sections in the format
228 // string are described in the table below.
232 // One - The format string applies to all values.
234 // Two - The first section applies to positive values
235 // and zeros, and the second section applies to negative values. If the number
236 // to be formatted is negative, but becomes zero after rounding according to
237 // the format in the second section, then the resulting zero is formatted
238 // according to the first section.
240 // Three - The first section applies to positive
241 // values, the second section applies to negative values, and the third section
242 // applies to zeros. The second section may be left empty (by having no
243 // characters between the semicolons), in which case the first section applies
244 // to all non-zero values. If the number to be formatted is non-zero, but
245 // becomes zero after rounding according to the format in the first or second
246 // section, then the resulting zero is formatted according to the third
249 // For both standard and user-defined formatting operations on values of type
250 // float and double, if the value being formatted is a NaN (Not
251 // a Number) or a positive or negative infinity, then regardless of the format
252 // string, the resulting string is given by the NaNSymbol,
253 // PositiveInfinitySymbol, or NegativeInfinitySymbol property of
254 // the NumberFormatInfo used to format the number.
258 // The Parse methods provided by the numeric classes are all of the form
260 // public static XXX Parse(String s);
261 // public static XXX Parse(String s, int style);
262 // public static XXX Parse(String s, int style, NumberFormatInfo info);
264 // where XXX is the name of the particular numeric class. The methods convert a
265 // string to a numeric value. The optional style parameter specifies the
266 // permitted style of the numeric string. It must be a combination of bit flags
267 // from the NumberStyles enumeration. The optional info parameter
268 // specifies the NumberFormatInfo instance to use when parsing the
269 // string. If the info parameter is null or omitted, the numeric
270 // formatting information is obtained from the current culture.
272 // Numeric strings produced by the Format methods using the Currency,
273 // Decimal, Engineering, Fixed point, General, or Number standard formats
274 // (the C, D, E, F, G, and N format specifiers) are guaranteed to be parseable
275 // by the Parse methods if the NumberStyles.Any style is
276 // specified. Note, however, that the Parse methods do not accept
277 // NaNs or Infinities.
278 internal static partial class Number
280 [MethodImpl(MethodImplOptions.InternalCall)]
281 public static extern string FormatDecimal(decimal value, string format, NumberFormatInfo info);
283 [MethodImpl(MethodImplOptions.InternalCall)]
284 public static extern string FormatDouble(double value, string format, NumberFormatInfo info);
286 [MethodImpl(MethodImplOptions.InternalCall)]
287 public static extern string FormatSingle(float value, string format, NumberFormatInfo info);
289 public static unsafe bool NumberBufferToDecimal(ref Number.NumberBuffer number, ref decimal value)
291 fixed (Number.NumberBuffer* numberPtr = &number)
293 return NumberBufferToDecimal((byte*)numberPtr, ref value);
297 public static unsafe bool NumberBufferToDouble(ref Number.NumberBuffer number, ref double value)
299 fixed (Number.NumberBuffer* numberPtr = &number)
301 return NumberBufferToDouble((byte*)numberPtr, ref value);
305 [MethodImpl(MethodImplOptions.InternalCall)]
306 private unsafe static extern bool NumberBufferToDecimal(byte* number, ref decimal value);
308 [MethodImpl(MethodImplOptions.InternalCall)]
309 private unsafe static extern bool NumberBufferToDouble(byte* number, ref double value);