Chapter 8. Numbers and Dates

This chapter compares the support for numbers, dates, and times provided in the Java class library with those in Microsoft .NET. Java and C# both provide language-level support for straightforward numeric operations; more complex features are implemented in the class libraries. Conversely, neither Java nor C# provides language-level support for working with dates and times; classes offer a better solution to the complexities of localization.

Numbers

The .NET numeric types and the C# language syntax used to manipulate them are discussed in Chapter 5. As described in Chapter 5, .NET value types are implemented as structs and have object capabilities. This section discusses the object features of the numeric types, particularly those that support comparison, conversion, and formatting. In Java, the primitive wrapper classes such as java.lang.Integer and java.lang.Double predominantly provide these features. This section also covers the facilities provided by .NET to perform mathematical operations and generate pseudorandom numbers; both provide direct equivalents of the facilities offered by Java.

Numbers as Objects

.NET implements all inbuilt numeric data types as structs in the System namespace. C# defines convenient keyword aliases for the fully qualified struct names, so the full names are rarely used. We discussed the C# keywords and their equivalent fully qualified struct names in Chapter 4.

All of the numeric structs derive from the System.ValueType class, which derives from System.Object. The Equals, GetHashCode, and ToString methods inherited from Object are overridden to provide behavior more appropriate to numeric types. GetType still returns a Type object for the struct instance. We’ll discuss these methods in the Members section later in this chapter. Additionally, all numeric structs implement a standard set of interfaces, provide type-specific members, and are serializable.

More Info

For a complete discussion of serialization, see Chapter 10.

Interfaces

All of the inbuilt numeric types implement the IComparable, IFormattable, and IConvertible interfaces from the System namespace.

IComparable

The IComparable interface specifies the implementation of the following method:

int CompareTo(object obj);

The CompareTo method enables instances of numeric types to be compared with other numbers, with the return value indicating their relative ranking. This is the same as the Java java.lang.Comparable interface, and the return values are

  • < 0 if the instance value is less than the value of obj.

  • 0 if the instance value is equal to the value of obj.

  • > 0 if the instance value is greater than the value of obj.

Unfortunately, although the CompareTo method accepts any Object reference as an argument, the numeric types throw a System.ArgumentException if the object and the argument are different types. No implicit conversion is performed; the types must match or have been explicitly cast to the same type. The value null is a valid value and is always considered less than any other value.

Implementation of the IComparable interface is useful when numeric types are used in collections, but for general purposes the >, ==, and < operators offer a simpler solution.

More Info

See Chapter 9, for information on the use of IComparable in collections.

IFormattable

IFormattable specifies the implementation of an overloaded ToString method that supports the rendering of numeric types to strings. Format specifiers and localization settings provide extensive control over the format of the string representation. See the Formatting Numbers section later in this chapter for more information.

More Info

The IFormattable interface is discussed in detail in Chapter 7.

IConvertible

The IConvertible interface specifies methods for converting the implementing class to a set of target representations. The methods are ToBoolean, ToByte, ToChar, ToDataTime, ToDecimal, ToDouble, ToInt16, ToInt32, ToInt64, ToSByte, ToSingle, ToString, ToType, ToUInt32, and ToUInt64. All methods take an instance of IFormatProvider as an argument. The implementing class refers to the IFormatProvider instance to obtain localization settings for use in the conversion process. If null is provided, the current default system settings will be used. If no meaningful conversion exists between two types, a System.InvalidCastException is thrown.

The IConvertible interface also includes the GetTypeCode member. GetTypeCode returns a member of the System.TypeCode enumeration that uniquely identifies the implementing type.

Although the inbuilt numeric types implement IConvertible, explicit interface implementation means it is not possible to invoke IConvertible members through an instance of the numeric type. The .NET documentation recommends conversion of numeric types be carried out using the static members of the System.Convert utility class as opposed to invoking IConvertible members directly. Alternatively, the implicit and explicit conversion support in C# is sufficient for most purposes. We’ll discuss the System.Convert class later, in the Converting Numbers section.

Members

Aside from the methods required by the interface implementations described earlier, all numeric types implement the members described in Table 8-1.

Table 8-1. Numeric Type Members

Member

Description

Public Fields

 

MaxValue

Constant containing the maximum value representable by the numeric type.

MinValue

Constant containing the minimum value representable by the numeric type.

Methods

 

Equals()

Overridden method inherited from System.Object. Returns true if the argument provided is of the same type and value as the instance; otherwise, returns false. Implicit conversion is not used; however, explicitly casting types with the same value will return true.

ToString()

The ToString method inherited from System.Object is overridden and calls the overloaded IFormattable.ToString method, passing it default formatting arguments.

GetHashCode()

Overridden. Returns a hash code appropriate to the numeric type.

GetType()

Inherited from System.Object. Returns a Type object for the numeric type.

Parse()

Converts a string representation of a number to an instance of the numeric type.

Floating-point members

System.Single and System.Double contain additional members, described in Table 8-2, to support floating-point operations.

Table 8-2. Additional System.Single and System.Double Members

Member

Description

Public Fields

 

Epsilon

Constant containing the smallest positive value greater than 0 representable by the floating-point type.

NaN

Constant representing "Not a Number."

NegativeInfinity

Constant representing negative infinity.

PositiveInfinity

Constant representing positive infinity.

Methods

 

IsInfinity

Static method returns true if the specified number evaluates to negative or positive infinity.

IsNaN

Static method returns true if the specified number evaluates to a value that is not a number.

IsNegativeInfinity

Static method returns true if the specified number evaluates to negative infinity.

IsPositiveInfinity

Static method returns true if the specified number evaluates to positive infinity.

TryParse()

Converts a string representation of a floating-point number to an instance of the numeric type. Returns true if the string is parsed successfully; does not throw an exception.

Decimal members

The System.Decimal type directly exposes methods to perform basic mathematical operations on Decimal instances. While these may be useful for programmers of languages other than C#, they provide no benefit over using the inbuilt C# syntax and will not be covered here.

Converting Numbers

C# language syntax supports implicit and explicit conversion from one numeric type to another. The .NET class library also includes a utility class named System.Convert that contains static methods for converting from one numeric type to another, including support for conversions between numbers and bool, string, and DateTime values.

The Convert class implements the following static methods: ToBoolean, ToByte, ToChar, ToDateTime, ToDecimal, ToDouble, ToInt16, ToInt32, ToInt64, ToSByte, ToSingle, ToString, ToUInt16, ToUInt32, and ToUInt64. Each of these methods provides overloads that take each of the numeric types and return the appropriately converted value. If no meaningful conversion exists between two types, a System.InvalidCastException is thrown.

Formatting Numbers

All numeric types implement the IFormattable interface. IFormattable specifies the implementation of a ToString method with the following signature:

string ToString(string format, IFormatProvider formatProvider);

The format argument takes what’s called a numeric format string, which determines how the number is formatted. The formatProvider argument provides information on localization setting to assist in the formatting process. If format-Provider is null, default localization settings are used.

In the following example, we use the numeric format string E2, which indicates scientific notation to two decimal places, and we specify null as the IFormatProvider so that the default localization settings are used.

int SomeInt = 1234567;

System.Console.WriteLine(SomeInt.ToString("E2", null));

The code produces the following output:

1.23E+006

As shown in this example, the ToString method of a numeric type can be called directly; more commonly, a number is formatted indirectly through one of the string formatting methods such as those provided by Console.WriteLine. When you’re using the string formatting methods, it’s important to understand that only the portion of the format specifier after the semicolon is passed to the ToString method of the number being formatted. For example, in the following statement:

Console.WriteLine("The amount is : {0,15:C2}", 1000000);

which, depending on localization settings, produces the following output:

The amount is :     $1,000,000.00

only the C2 (in boldface) is used to format the literal 1000000, equivalent to the following direct ToString call:

1000000.ToString("C2", null);

More Info

String formatting methods are discussed fully in Chapter 7.

Standard Numeric Format Strings

A standard numeric format string is a single letter followed by an optional pair of digits called the precision specifier. The purpose of the precision specifier depends on the format string used, and if not provided will default to a setting appropriate for the current system settings. The standard format strings are summarized in Table 8-3. The examples use an overloaded ToString method that takes a format string argument but that does not require an IFormatProvider instance.

Table 8-3. Numeric Format Strings

Format String

Description and Examples

C or c

Formats the number as a currency amount. The currency symbol, thousands separator, and decimal separator are determined by localization settings. The precision specifier controls the number of decimal places displayed. For example:

1234.ToString("C") = $1,234.00
1234.5678.ToString("c2") = $1,234.57
1234.5678.ToString("C6") = $1,234.567800

D or d

The decimal format string is applicable only to integral types and displays the number as a string of decimal digits. The precision specifier controls the minimum number of digits that appear in the output string; output is left padded with 0s if needed. For example:

1234.ToString("D7") = 0001234
0xABC.ToString("d") = 2748

E or e

Formats the number in scientific notation with the case of the exponent prefix matching the case of the format string. The precision specifier controls the number of digits displayed after the decimal point. For example:

1234.ToString("e7") = 1.2340000e+003
12.345678.ToString("E3") = 1.235E+001

F or f

Formats the number to a fixed-point decimal representation. The precision specifier controls the number of digits after the decimal point. For example:

1234.ToString("F4") = 1234.0000
12.345678.ToString("F3") = 12.346

G or g

Formats the number in the most compact decimal form using fixed or scientific notation. The precision specifier controls the number of significant digits displayed.

N or n

Formats the number using the current thousands separator and decimal separator. The precision specifier controls the minimum number of decimal digits displayed. For example:

1234.56789.ToString("N") = 1,234.57
1234567.89.ToString("N3") = 1,234,567.890

P or p

Multiplies the number by 100 and formats it as a percentage. The percent symbol and its location are determined by localization settings. The precision specifier controls the number of decimal places displayed. For example:

1.23.ToString("P4") = 123.0000  %
1.234567.ToString("p2") = 123.46  %

R or r

Round-trip formatting is applicable only to floating-point types and guarantees that a floating-point string resulting from formatting will be parsed back into the same numeric value. The precision specifier is not used and is ignored if provided.

X or x

The hexadecimal format string is applicable to integral types only and converts the number to a hexadecimal digit representation. The case of the format string controls the case of the hexadecimal digits in the output. The precision specifier controls the minimum number of hexadecimal digits; the output is left padded with 0s if necessary. For example:

2748.ToString("X") = ABC
2748.ToString("x5") = 00abc

.NET interprets any format string that is a single character followed by optional digits as a standard numeric format string. If the character doesn’t match one of those in Table 8-3, ToString throws a FormatException. A format string containing more than one character is a custom format string.

Custom Numeric Format Strings

Custom format strings map closely to the formatting functionality provided by the java.text.DecimalFormat class; custom format strings offer greater flexibility over how a number will be formatted. Custom format strings use a small selection of symbols to define the desired format of a numeric type. Table 8-4 provides a summary of the available symbols.

Table 8-4. Custom Numeric Format Strings

Format Character

Comments

0

The zero placeholder causes a digit or 0 to appear in the output string. For example:

123.ToString("00000") = 00123

#

The digit placeholder causes a digit or nothing to appear in the output string. For example:

123.45.ToString("#####") = 123

.

The decimal point identifies the position of the first decimal place. For example:

123.45.ToString("#####.000") = 123.450

,

The comma indicates that thousands separators should be used. For example:

12345678.ToString("#,#") = 12,345,678

%

The percent symbol causes the number to be multiplied by 100 and displayed as a percentage. For example:

0.1234.ToString("%#.00") = %12.34

E0, E+0, E-0,

e0, e+0, e-0

Use scientific notation. For example:

1234.ToString("0.##E+000") = 1.23E+003
1234.ToString("0.##e+000") = 1.23e+003
1234.ToString("0.##e0") = 1.23e3

The backslash escapes the next character. For example:

1234.ToString("##	##") = 12    34

;

Different formats can be specified for use with positive and negative numbers and 0. The semicolon is used to separate these format elements. For example:

1234.ToString("##;(##);zero") = 1234
(1234).ToString("##;(##);zero") = (1234)
0.ToString("##;(##);zero") = zero

Other

Other characters are copied to the output string without affecting numeric formatting. For example:

12345.ToString("A[##][00]") = A[123][45]

Mathematical Functions

The java.lang.Math class is equivalent to the .NET System.Math class. Both classes provide a set of constants and static methods for performing mathematical operations. The methods common to both System.Math and java.lang.Math are, using the .NET names, as follows: Acos, Asin, Atan, Atan2, Ceiling, Cos, Exp, Floor, IEEERemainder, Max, Min, Pow, Sin, Sqrt, and Tan. Table 8-5 highlights the differences between the java.lang.Math and System.Math classes.

Table 8-5. Differences in Static Members of java.lang.Math and System.Math

Java

.NET

Comments

abs()

Abs()

.NET provides overloads that take a larger range of parameter types.

N/A

Cosh()

Returns the hyperbolic cosine of the specified angle.

log()

Log()

.NET provides an overloaded Log method that allows the base of the logarithm to be specified.

N/A

Log10()

A convenience method for getting the base 10 logarithm of a number.

random()

N/A

See the next section, Random Numbers.

rint()

round()

Round()

The .NET Round method is more like Java rint than round. It returns a floating-point representation of the rounded number as opposed to an integer value.

.NET provides an overloaded Round method that supports rounding to a specified precision.

N/A

Sign()

Returns a value indicating the sign of the specified number.

N/A

Sinh()

Returns the hyperbolic sine of the specified angle.

N/A

Tanh()

Returns the hyperbolic tangent of the specified angle.

toDegrees()

N/A

 

toRadians()

N/A

 

Random Numbers

The Java class java.util.Random and the .NET equivalent System.Random are simple classes for generating pseudorandom numbers. These classes are not suitable for high-security or cryptography applications.

Note

The .NET System.Security.Cryptography namespace includes mechanisms for the generation of secure random numbers (SRNs).

Both Random classes act as number generators, providing a stream of random numbers in response to method calls. Instantiation of both classes is the same except when specifying a seed; java.util.Random takes a long, whereas System.Random takes an int. Once created, the .NET System.Random class cannot have its seed changed, whereas the Java class provides the setSeed method.

Java offers greater flexibility in the type of result returned from Random, including support for Boolean values and a wider selection of numeric types.

Table 8-6 summarizes the methods of the Java and .NET Random classes.

Table 8-6. A Comparison between Java and .NET Random Classes

Java

.NET

Comments

Constructors

  

Random()

Random()

 

Random(long)

Random(int)

Uses the specified value as the seed for the random number generation algorithm.

Methods

  

nextBoolean()

N/A

 

nextBytes()

NextBytes()

 

nextDouble()

NextDouble()

 

nextFloat()

N/A

 

nextGaussian()

N/A

 

nextInt()

Next()

 

nextInt(int)

Next(int)

 

N/A

Next(int, int)

Returns a positive random integer between the specified values.

nextLong()

N/A

 

setSeed()

N/A

.NET Random seed is set only during construction.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset