Jump to content

How to Format Numeric Strings in C# 4.0

0
  chco's Photo
Posted Aug 21 2010 04:14 PM

This excerpt from Programming C# 4.0, Sixth Edition covers the standard ways you can format numeric strings.
In most instances, we’re not dreaming up a brand-new format for our numeric strings; if we were, people probably wouldn’t understand what we meant. Consequently, the framework provides us with a whole bunch of standard numeric format strings, for everyday use. Let’s have a look at them in action.

Currency

Example 10-7 shows how we format a decimal as a currency value, using an overload of the standard ToString method.

Example 10-7. Currency format

decimal dollarAmount = 123165.4539M;
string text = dollarAmount.ToString("C");

Console.WriteLine(text);


The capital C indicates that we want the decimal formatted as if it were a currency value; and here’s the output:

$123,165.45


Notice how it has rounded to two decimal places (rounding down in this case), added a comma to group the digits, and inserted a dollar sign for us.

Note: Actually, I’ve lied to you a bit. On my machine the output looked like this:That’s because it is configured for UK English, not U.S. English, and my default currency symbol is the one for pounds sterling. We’ll talk about formatting and globalization a little later in this chapter.
£123,165.45


That’s the simplest form of this “currency” format. We can also add a number after the C to indicate the number of decimal places we want to use, as Example 10-8 shows.

Example 10-8. Specifying decimal places with currency format

decimal dollarAmount = 123165.4539M;
string text = dollarAmount.ToString("C3");

Console.WriteLine(text);


This will produce three decimal places in the output:

$123,165.454


Notice that it is again rounding the result. If you want to truncate, or always round up, you’ll need to round the original value before you convert to a string.

This formatting style is available on all of the numeric types. (We’ll see some later that apply to only particular types.)

Decimal

Decimal formatting is a bit confusingly named, as it actually applies to integer types, not the decimal type. It gets its name from the fact that it displays the number as a string of decimal digits (0–9), with a preceding minus sign (−) if necessary. Example 10-9 uses this format.

Example 10-9. Decimal format, with explicit precision

int amount = 1654539;
string text = amount.ToString("D9");


We’re asking for nine digits in the output string, and it pads with leading zeros:

001654539


If you don’t supply a qualifying number of decimal digits, as Example 10-10 shows, it just uses as many as necessary.

Example 10-10. Decimal format with unspecified precision

int amount = -2895729;
string text = amount.ToString("D");


This produces:

−2895729


Hexadecimal

Another one for integer types, hexadecimal formatting, shown in Example 10-11, represents numbers as a string of hex digits (0–9, A–F).

Example 10-11. Hexadecimal format

int amount = 256;
string text = amount.ToString("X");


This produces the output:

100


As with the decimal format string, you can specify a number to indicate the total number of digits to which to pad the number, as shown in Example 10-12.

Example 10-12. Hexadecimal format with explicit precision

int amount = 256;
string text = amount.ToString("X4");


This produces the output:

0100


Notice that the method doesn’t prepend a 0x or similar; so there is nothing to distinguish this as a hex string, if you happen to hit a value that does not include the digits A–F. (The convention of preceding hexadecimal values with 0x is common in C family languages, which is why C# supports it for numeric constants, but it’s not universal. VB.NET uses the prefix &H, for example. All .NET languages share the same numeric types and formatting services, so if they printed hex numbers with a C# prefix, that would be annoying for users of other languages. If you want a prefix, you have to add it yourself.)

Exponential form

All numeric types can be expressed in exponential form. You will probably be familiar with this notation. For example, 1.05 × 103 represents the number 1050, and 1.05 × 10−3 represents the number 0.00105.

Developers use plain text editors, which don’t support formatting such as superscript, so there’s a convention for representing exponential numbers with plain, unformatted text. We can write those last two examples as 1.05E+003 and 1.05E-003, respectively. C# recognizes this convention for literal floating-point values. But we can also use it when printing out numbers.

To display this form, we use the format string E, with the numeric specifier determining how many decimal places of precision we use.

Note: It will always format the result with one digit to the left of the decimal point, so you could also think of the precision specified as “one less than the number of significant figures.”

Example 10-13 asks for exponential formatting with four digits of precision.

Example 10-13. Exponential format

double amount = 254.23875839484;
string text = amount.ToString("E4");


And here’s the string it produces:

2.5424E+002


If you don’t provide a precision specifier, as in Example 10-14, you get six digits to the right of the decimal point (or fewer, if the trailing digits would be zero).

Note: We’ll see later how these defaults can be controlled by the framework’s globalization features

Example 10-14. Exponential format without precision

double amount = 254.23875839484;
string text = amount.ToString("E");


This produces:

2.542388E+002


Fixed point

Another format string that applies to all numeric types, the fixed-point format provides the ability to display a number with a specific number of digits after the decimal point. As usual, it rounds the result, rather than truncating. Example 10-15 asks for four digits after the decimal point.

Example 10-15. Fixed-point format

double amount = 152.68385485;
string text = amount.ToString("F4");


This produces:

152.6839


The output will be padded with trailing zeros if necessary. Example 10-16 causes this by asking for four digits where only two are required.

Example 10-16. Fixed-point format causing trailing zeros

double amount = 152.68;
string text = amount.ToString("F4");


So, the output in this case is:

152.6800


General

Sometimes you want to use fixed point, if possible, but if an occasional result demands a huge number of leading zeros, you’d prefer to fall back on the exponential form (rather than display it as zero, for instance). The “general” format string, illustrated in Example 10-17, will provide you with this behavior. It is available on all numeric types.

Example 10-17. General format

double amount = 152.68;
string text = amount.ToString("G4");
Console.WriteLine(text);

double amount2 = 0.00000000000015268;
text = amount2.ToString("G4");
Console.WriteLine(text);


This will produce the following output:

152.7
1.527E-13


Note that the precision string determines the number of significant figures in either case, not the number of decimal places (as per the fixed-point and exponential forms). As usual, rounding is used if there are more digits than the precision allows. And if you do not specify the precision (i.e., you just use "G") it chooses the number of digits based on the precision of the data you’re using—float will show fewer digits than double, for example.

Note: If you don’t specify a particular format string, the default is as though you had specified "G".

Numeric

The numeric format, shown in Example 10-18, is very similar to the fixed-point format, but adds a “group” separator for values with enough digits (just as the currency format does). The precision specifier can be used to determine the number of decimal places, and rounding is applied if necessary.

Example 10-18. Numeric format

double amount = 1520494.684848;
string text = amount.ToString("N4");
Console.WriteLine(text);


This will produce the following output:

1,520,494.6848


Percent

Very often you need to display a number as a percentage. However, it’s common to maintain values which represent a percentage using one of the floating-point types, predivided by 100 for ease of future manipulation.

The more mathematically minded among you probably rail against people calling the value 0.58 “a percentage” when they really mean 58%; but it is, unfortunately, a somewhat common convention in computer circles. Worse, it’s not consistently applied, making it hard to know whether you are dealing with predivided values, or “true” percentages. It can get especially confusing when you are frequently dealing with values less than 1 percent:

double interestRatePercent = 0.2;


Is that supposed to be 0.2 percent (like I get on my savings) or 20 percent APR (like my credit card)? One way to avoid ambiguity is to avoid mentioning “percent” in your variable names and always to store values as fractions, representing 100 percent as 1.0, converting into a percentage only when you come to display the number.

The percent format is useful if you follow this convention: it will multiply by 100, enabling you to work with ratios internally, but to display them as percentages where necessary. It displays numbers in a fixed-point format, and adds a percentage symbol for you. The precision determines the number of decimal places to use, with the usual rounding method applied. Example 10-19 asks for four decimal places.

Example 10-19. Percent format

double amount = 0.684848;
string text = amount.ToString("P4");
Console.WriteLine(text);


This will produce:

68.4848 %


Note that this format works with any numeric type—including the integer types. There’s no special treatment for an Int32 or Int16, for example. They are multiplied up by 100, in just the same way as the floating-point types. This means that you can’t format values in increments of less than 100 percent with an integer. For instance, 0 × 100 implies 0 percent, 1 × 100 implies 100 percent, and so on.

Round trip

The last of the standard numeric format strings we’re going to look at is the round-trip format. This is used when you are expecting the string value to be converted back into its numeric representation at some point in the future, and you want to guarantee no loss of precision.

This format has no use for a precision specifier, because by definition, we always want full precision. (You can provide one if you like, because all the standard numeric formats follow a common pattern, including an optional precision. This format supports the common syntax rules, it just ignores the precision.) The framework will use the most compact form it can to achieve the round-trip behavior. Example 10-20 shows this format in use.

Example 10-20. Round-trip format

double amount = 0.684848;
string text = amount.ToString("R");
Console.WriteLine(text);


This produces the following output:

0.684848


Cover of Programming C# 4.0
Learn more about this topic from Programming C# 4.0. 

This bestselling tutorial shows you how to build web, desktop, and rich Internet applications using C# 4.0 with .NET's database capabilities, UI framework (WPF), extensive communication services (WCF), and more. The sixth edition covers the latest enhancements to C#, as well as the fundamentals of both the language and framework. You'll learn concurrent programming with C# 4.0, and how to use .NET tools such as the Entity Framework for easier data access, and the Silverlight platform for browser-based RIA development.

Learn More Read Now on Safari


Tags:
0 Subscribe


0 Replies