CSharp/C# Tutorial - C# Numeric Types






C# has the predefined numeric types shown in the following Table.

Integral-signed

C# typeSystem typeSuffixSizeRange
sbyteSByteNo Suffix8 bits-27 to 27-1
shortInt16No Suffix16 bits-215 to 215-1
intInt32No Suffix32 bits-231 to 231-1
longInt64L64 bits-263 to 263-1

Integral-unsigned

C# typeSystem typeSuffixSizeRange
byteByteNo Suffix8 bits0 to 28-1
ushortUInt16No Suffix16 bits0 to 216-1
uintUInt32U32 bits0 to 232-1
ulongUInt64UL64 bits0 to 264-1

Real

C# typeSystem typeSuffixSizeRange
floatSingleF32 bits+/- (~10-45 to 1038)
doubleDoubleD64 bits+/- (~10-324 to 10308)
decimalDecimalM128 bits+/- (~10-28 to 1028)

The decimal type is typically used for financial calculations.





Numeric Literals

Integral literals can use decimal or hexadecimal notation; hexadecimal is denoted with the 0x prefix. For example:


int x = 1; 
long y = 0x7F; 

Real literals can use decimal and/or exponential notation. For example:


double d = 1.5; 
double million = 1E06; 

Numeric literal type inference

By default, the compiler infers a numeric literal to be either double or an integral type:

If the literal contains a decimal point or the exponential symbol (E), it is a double.

The literal's type is the first type in this list that can fit the literal's value: int, uint, long, and ulong.

For example:


Console.WriteLine ( 1.0.GetType());    // Double (double) 
Console.WriteLine ( 1E06.GetType());   // Double (double) 
Console.WriteLine ( 1.GetType());      // Int32 (int) 
Console.WriteLine ( 0xF0000000.GetType()); // UInt32 (uint) 





Numeric suffixes

Numeric suffixes explicitly define the type of a literal.

Suffixes can be either lower or uppercase, and are as follows:

CategoryC# typeExample
Ffloatfloat f = 1.0F;
Ddoubledouble d = 1D;
Mdecimaldecimal d = 1.0M;
Uuintuint i = 1U;
Llonglong i = 1L;
ULulongulong i = 1UL;

The F and M suffixes should always be applied when specifying float or decimal literals.

Without the F suffix, the following line would not compile, because 4.5 would be inferred to be of type double, which has no implicit conversion to float:


float f = 4.5F; 

The same principle is applied for a decimal literal:


decimal d = -1231.13M; // Will not compile without the M suffix. 

Integral to integral conversions

Integral conversions are implicit when the destination type can represent every possible value from the source type. Otherwise, an explicit conversion is required.

For example:


int x = 12345;        // int is a 32-bit integral 
long y = x;           // Implicit conversion to 64-bit integral 
short z = (short)x;   // Explicit conversion to 16-bit integral 

Floating-point to floating-point conversions

A float can be implicitly converted to a double, since a double can represent every possible value of a float.

The reverse conversion must be explicit.

Floating-point to integral conversions

All integral types may be implicitly converted to all floating-point types:


int i = 1; 
float f = i; 

The reverse conversion must be explicit:


int i2 = (int)f; 

When you cast from a floating-point number to an integral, any fractional portion is truncated(lost).

Decimal conversions

All integral types can be implicitly converted to the decimal type.

All other numeric conversions to and from a decimal type must be explicit.